Commit 81590d98 authored by Alessandro Rubini's avatar Alessandro Rubini

time-{unix,wrs}: prepare for PROTO_VLAN addition

Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 46c498d9
......@@ -316,6 +316,7 @@ extern int pp_config_file(struct pp_globals *ppg, int force, char *fname);
#define PPSI_PROTO_RAW 0
#define PPSI_PROTO_UDP 1
#define PPSI_PROTO_VLAN 2 /* Actually: vlan over raw eth */
#define PPSI_ROLE_AUTO 0
#define PPSI_ROLE_MASTER 1
......
......@@ -104,31 +104,38 @@ static int unix_net_recv(struct pp_instance *ppi, void *pkt, int len,
TimeInternal *t)
{
struct pp_channel *ch1, *ch2;
int ret;
int ret, fd;
if (ppi->proto == PPSI_PROTO_RAW) {
int fd = NP(ppi)->ch[PP_NP_GEN].fd;
switch(ppi->proto) {
case PPSI_PROTO_RAW:
fd = NP(ppi)->ch[PP_NP_GEN].fd;
ret = unix_recv_msg(ppi, fd, pkt, len, t);
if (ret > 0 && pp_diag_allow(ppi, frames, 2))
dump_1588pkt("recv: ", pkt, ret, t);
return ret;
}
/* else: UDP, we can return one frame only, always handle EVT msgs
* before GEN */
ch1 = &(NP(ppi)->ch[PP_NP_EVT]);
ch2 = &(NP(ppi)->ch[PP_NP_GEN]);
case PPSI_PROTO_UDP:
/* we can return one frame only, always handle EVT msgs
* before GEN */
ch1 = &(NP(ppi)->ch[PP_NP_EVT]);
ch2 = &(NP(ppi)->ch[PP_NP_GEN]);
ret = -1;
if (ch1->pkt_present)
ret = unix_recv_msg(ppi, ch1->fd, pkt, len, t);
else if (ch2->pkt_present)
ret = unix_recv_msg(ppi, ch2->fd, pkt, len, t);
ret = -1;
if (ch1->pkt_present)
ret = unix_recv_msg(ppi, ch1->fd, pkt, len, t);
else if (ch2->pkt_present)
ret = unix_recv_msg(ppi, ch2->fd, pkt, len, t);
if (ret > 0 && pp_diag_allow(ppi, frames, 2))
dump_payloadpkt("recv: ", pkt, ret, t);
return ret;
if (ret > 0 && pp_diag_allow(ppi, frames, 2))
dump_payloadpkt("recv: ", pkt, ret, t);
return ret;
case PPSI_PROTO_VLAN:
/* FIXME */
default:
return -1;
}
}
static int unix_net_send(struct pp_instance *ppi, void *pkt, int len,
......@@ -146,7 +153,8 @@ static int unix_net_send(struct pp_instance *ppi, void *pkt, int len,
return len;
}
if (ppi->proto == PPSI_PROTO_RAW) {
switch(ppi->proto) {
case PPSI_PROTO_RAW:
hdr->h_proto = htons(ETH_P_1588);
memcpy(hdr->h_dest, PP_MCAST_MACADDRESS, ETH_ALEN);
......@@ -160,22 +168,28 @@ static int unix_net_send(struct pp_instance *ppi, void *pkt, int len,
if (pp_diag_allow(ppi, frames, 2))
dump_1588pkt("send: ", pkt, len, t);
return ret;
}
/* else: UDP */
addr.sin_family = AF_INET;
addr.sin_port = htons(chtype == PP_NP_GEN ? PP_GEN_PORT : PP_EVT_PORT);
case PPSI_PROTO_UDP:
addr.sin_family = AF_INET;
addr.sin_port = htons(chtype == PP_NP_GEN
? PP_GEN_PORT : PP_EVT_PORT);
addr.sin_addr.s_addr = NP(ppi)->mcast_addr;
addr.sin_addr.s_addr = NP(ppi)->mcast_addr;
if (t)
ppi->t_ops->get(ppi, t);
if (t)
ppi->t_ops->get(ppi, t);
ret = sendto(NP(ppi)->ch[chtype].fd, pkt, len, 0,
(struct sockaddr *)&addr,
sizeof(struct sockaddr_in));
if (pp_diag_allow(ppi, frames, 2))
dump_payloadpkt("send: ", pkt, len, t);
return ret;
ret = sendto(NP(ppi)->ch[chtype].fd, pkt, len, 0,
(struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if (pp_diag_allow(ppi, frames, 2))
dump_payloadpkt("send: ", pkt, len, t);
return ret;
case PPSI_PROTO_VLAN:
/* FIXME */
default:
return -1;
}
}
/* To open a channel we must bind to an interface and so on */
......@@ -193,7 +207,8 @@ static int unix_open_ch(struct pp_instance *ppi, char *ifname, int chtype)
char addr_str[INET_ADDRSTRLEN];
char *context;
if (ppi->proto == PPSI_PROTO_RAW) {
switch(ppi->proto) {
case PPSI_PROTO_RAW:
/* open socket */
context = "socket()";
sock = socket(PF_PACKET, SOCK_RAW, ETH_P_1588);
......@@ -240,99 +255,106 @@ static int unix_open_ch(struct pp_instance *ppi, char *ifname, int chtype)
&temp, sizeof(int));
return 0;
}
/* else: UDP */
context = "socket()";
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0)
goto err_out;
case PPSI_PROTO_UDP:
context = "socket()";
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0)
goto err_out;
NP(ppi)->ch[chtype].fd = sock;
NP(ppi)->ch[chtype].fd = sock;
/* hw interface information */
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, ifname);
context = "ioctl(SIOCGIFINDEX)";
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0)
goto err_out;
/* hw interface information */
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, ifname);
context = "ioctl(SIOCGIFINDEX)";
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0)
goto err_out;
context = "ioctl(SIOCGIFHWADDR)";
if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
goto err_out;
context = "ioctl(SIOCGIFHWADDR)";
if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
goto err_out;
memcpy(NP(ppi)->ch[chtype].addr, ifr.ifr_hwaddr.sa_data, 6);
context = "ioctl(SIOCGIFADDR)";
if (ioctl(sock, SIOCGIFADDR, &ifr) < 0)
goto err_out;
memcpy(NP(ppi)->ch[chtype].addr, ifr.ifr_hwaddr.sa_data, 6);
context = "ioctl(SIOCGIFADDR)";
if (ioctl(sock, SIOCGIFADDR, &ifr) < 0)
goto err_out;
iface_addr.s_addr =
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
iface_addr.s_addr =
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
pp_diag(ppi, frames, 2, "Local IP address used : %s\n",
pp_diag(ppi, frames, 2, "Local IP address used : %s\n",
inet_ntoa(iface_addr));
temp = 1; /* allow address reuse */
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
&temp, sizeof(int)) < 0)
pp_printf("%s: ioctl(SO_REUSEADDR): %s\n", __func__,
strerror(errno));
/* bind sockets */
/* need INADDR_ANY to allow receipt of multi-cast and uni-cast
* messages */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(chtype == PP_NP_GEN ? PP_GEN_PORT : PP_EVT_PORT);
context = "bind()";
if (bind(sock, (struct sockaddr *)&addr,
sizeof(struct sockaddr_in)) < 0)
goto err_out;
/* Init General multicast IP address */
memcpy(addr_str, PP_DEFAULT_DOMAIN_ADDRESS, INET_ADDRSTRLEN);
context = addr_str; errno = EINVAL;
if (!inet_aton(addr_str, &net_addr))
goto err_out;
NP(ppi)->mcast_addr = net_addr.s_addr;
/* multicast sends only on specified interface */
imr.imr_multiaddr.s_addr = net_addr.s_addr;
imr.imr_interface.s_addr = iface_addr.s_addr;
context = "setsockopt(IP_MULTICAST_IF)";
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0)
goto err_out;
/* join multicast group (for receiving) on specified interface */
context = "setsockopt(IP_ADD_MEMBERSHIP)";
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&imr, sizeof(struct ip_mreq)) < 0)
goto err_out;
/* End of General multicast Ip address init */
/* set socket time-to-live */
context = "setsockopt(IP_MULTICAST_TTL)";
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,
&OPTS(ppi)->ttl, sizeof(int)) < 0)
goto err_out;
/* forcibly disable loopback */
temp = 0;
context = "setsockopt(IP_MULTICAST_LOOP)";
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
&temp, sizeof(int)) < 0)
goto err_out;
/* make timestamps available through recvmsg() */
context = "setsockopt(SO_TIMESTAMP)";
if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
&temp, sizeof(int)) < 0)
goto err_out;
NP(ppi)->ch[chtype].fd = sock;
return 0;
temp = 1; /* allow address reuse */
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
&temp, sizeof(int)) < 0)
pp_printf("%s: ioctl(SO_REUSEADDR): %s\n", __func__,
strerror(errno));
/* bind sockets */
/* need INADDR_ANY to allow receipt of multi-cast and uni-cast
* messages */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(chtype == PP_NP_GEN
? PP_GEN_PORT : PP_EVT_PORT);
context = "bind()";
if (bind(sock, (struct sockaddr *)&addr,
sizeof(struct sockaddr_in)) < 0)
goto err_out;
/* Init General multicast IP address */
memcpy(addr_str, PP_DEFAULT_DOMAIN_ADDRESS, INET_ADDRSTRLEN);
context = addr_str; errno = EINVAL;
if (!inet_aton(addr_str, &net_addr))
goto err_out;
NP(ppi)->mcast_addr = net_addr.s_addr;
/* multicast sends only on specified interface */
imr.imr_multiaddr.s_addr = net_addr.s_addr;
imr.imr_interface.s_addr = iface_addr.s_addr;
context = "setsockopt(IP_MULTICAST_IF)";
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&imr.imr_interface.s_addr,
sizeof(struct in_addr)) < 0)
goto err_out;
/* join multicast group (for recv) on specified interface */
context = "setsockopt(IP_ADD_MEMBERSHIP)";
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&imr, sizeof(struct ip_mreq)) < 0)
goto err_out;
/* End of General multicast Ip address init */
/* set socket time-to-live */
context = "setsockopt(IP_MULTICAST_TTL)";
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,
&OPTS(ppi)->ttl, sizeof(int)) < 0)
goto err_out;
/* forcibly disable loopback */
temp = 0;
context = "setsockopt(IP_MULTICAST_LOOP)";
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
&temp, sizeof(int)) < 0)
goto err_out;
/* make timestamps available through recvmsg() */
context = "setsockopt(SO_TIMESTAMP)";
if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
&temp, sizeof(int)) < 0)
goto err_out;
NP(ppi)->ch[chtype].fd = sock;
return 0;
case PPSI_PROTO_VLAN:
/* FIXME */
default:
return -1;
}
err_out:
pp_printf("%s: %s: %s\n", __func__, context, strerror(errno));
......@@ -359,26 +381,26 @@ static int unix_net_init(struct pp_instance *ppi)
/* The buffer is inside ppi, but we need to set pointers and align */
pp_prepare_pointers(ppi);
if (ppi->proto == PPSI_PROTO_RAW) {
switch(ppi->proto) {
case PPSI_PROTO_RAW:
pp_diag(ppi, frames, 1, "unix_net_init IEEE 802.3\n");
/* raw sockets implementation always use gen socket */
return unix_open_ch(ppi, ppi->iface_name, PP_NP_GEN);
}
/* else: UDP */
pp_diag(ppi, frames, 1, "unix_net_init UDP\n");
if (ppi->nvlans) {
/* If "proto udp" is set after setting vlans... */
pp_printf("Error: can't use UDP with VLAN support\n");
exit(1);
}
for (i = PP_NP_GEN; i <= PP_NP_EVT; i++) {
if (unix_open_ch(ppi, ppi->iface_name, i))
return -1;
}
case PPSI_PROTO_UDP:
pp_diag(ppi, frames, 1, "unix_net_init UDP\n");
for (i = PP_NP_GEN; i <= PP_NP_EVT; i++) {
if (unix_open_ch(ppi, ppi->iface_name, i))
return -1;
}
return 0;
return 0;
case PPSI_PROTO_VLAN:
/* FIXME */
default:
return -1;
}
}
/*
......@@ -390,36 +412,38 @@ static int unix_net_exit(struct pp_instance *ppi)
int fd;
int i;
if (ppi->proto == PPSI_PROTO_RAW) {
switch(ppi->proto) {
case PPSI_PROTO_RAW:
fd = NP(ppi)->ch[PP_NP_GEN].fd;
if (fd > 0) {
close(fd);
NP(ppi)->ch[PP_NP_GEN].fd = -1;
}
return 0;
}
/* else: UDP */
for (i = PP_NP_GEN; i <= PP_NP_EVT; i++) {
fd = NP(ppi)->ch[i].fd;
if (fd < 0)
continue;
/* Close General Multicast */
imr.imr_multiaddr.s_addr = NP(ppi)->mcast_addr;
imr.imr_interface.s_addr = htonl(INADDR_ANY);
case PPSI_PROTO_UDP:
for (i = PP_NP_GEN; i <= PP_NP_EVT; i++) {
fd = NP(ppi)->ch[i].fd;
if (fd < 0)
continue;
setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
&imr, sizeof(struct ip_mreq));
/* Close General Multicast */
imr.imr_multiaddr.s_addr = NP(ppi)->mcast_addr;
imr.imr_interface.s_addr = htonl(INADDR_ANY);
close(fd);
setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
&imr, sizeof(struct ip_mreq));
close(fd);
NP(ppi)->ch[i].fd = -1;
NP(ppi)->ch[i].fd = -1;
}
NP(ppi)->mcast_addr = 0;
return 0;
case PPSI_PROTO_VLAN:
/* FIXME */
default:
return -1;
}
NP(ppi)->mcast_addr = 0;
return 0;
}
static int unix_net_check_packet(struct pp_globals *ppg, int delay_ms)
......
......@@ -245,15 +245,18 @@ int wrs_net_recv(struct pp_instance *ppi, void *pkt, int len,
TimeInternal *t)
{
struct pp_channel *ch1, *ch2;
int ret = -1;
int fd, ret = -1;
if (ppi->proto == PPSI_PROTO_RAW) {
int fd = NP(ppi)->ch[PP_NP_GEN].fd;
switch(ppi->proto) {
case PPSI_PROTO_RAW:
fd = NP(ppi)->ch[PP_NP_GEN].fd;
ret = wrs_recv_msg(ppi, fd, pkt, len, t);
if (ret > 0 && pp_diag_allow(ppi, frames, 2))
dump_1588pkt("recv: ", pkt, ret, t);
} else {
break;
case PPSI_PROTO_UDP:
/* UDP: always handle EVT msgs before GEN */
ch1 = &(NP(ppi)->ch[PP_NP_EVT]);
ch2 = &(NP(ppi)->ch[PP_NP_GEN]);
......@@ -265,7 +268,14 @@ int wrs_net_recv(struct pp_instance *ppi, void *pkt, int len,
if (ret > 0 && pp_diag_allow(ppi, frames, 2))
dump_payloadpkt("recv: ", pkt, ret, t);
break;
case PPSI_PROTO_VLAN:
/* FIXME */
default:
return -1;
}
if (ret < 0)
return ret;
pp_diag(ppi, time, 1, "recv stamp: (correct %i) %9li.%09li\n",
......@@ -337,10 +347,10 @@ static void poll_tx_timestamp(struct pp_instance *ppi, void *pkt, int len,
/*
* Raw frames return "sock_extended_err" too, telling this is
* a tx timestamp. Udp doesn't so don't check in udp mode
* a tx timestamp. UDP does not; so don't check in udp mode
* (the pointer is only checked for non-null)
*/
if (!(ppi->proto == PPSI_PROTO_RAW))
if (!(ppi->proto != PPSI_PROTO_UDP))
serr = (void *)1;
for (cmsg = CMSG_FIRSTHDR(&msg);
......@@ -384,7 +394,8 @@ int wrs_net_send(struct pp_instance *ppi, void *pkt, int len,
*/
drop = ppsi_drop_tx();
if (ppi->proto == PPSI_PROTO_RAW) {
switch (ppi->proto) {
case PPSI_PROTO_RAW:
fd = NP(ppi)->ch[PP_NP_GEN].fd;
hdr->h_proto = htons(ETH_P_1588);
if (drop)
......@@ -401,7 +412,7 @@ int wrs_net_send(struct pp_instance *ppi, void *pkt, int len,
poll_tx_timestamp(ppi, pkt, len, s, fd, t);
if (drop) /* avoid messaging about stamps that are not used */
goto drop_msg;
break;
if (pp_diag_allow(ppi, frames, 2))
dump_1588pkt("send: ", pkt, len, t);
......@@ -409,28 +420,35 @@ int wrs_net_send(struct pp_instance *ppi, void *pkt, int len,
t->correct, (long)t->seconds,
(long)t->nanoseconds);
return ret;
}
/* else: UDP */
fd = NP(ppi)->ch[chtype].fd;
addr.sin_family = AF_INET;
addr.sin_port = htons(chtype == PP_NP_GEN ? PP_GEN_PORT : PP_EVT_PORT);
addr.sin_addr.s_addr = NP(ppi)->mcast_addr;
if (drop)
addr.sin_port = 3200;
ret = sendto(fd, pkt, len, 0,
(struct sockaddr *)&addr, sizeof(struct sockaddr_in));
poll_tx_timestamp(ppi, pkt, len, s, fd, t);
case PPSI_PROTO_UDP:
fd = NP(ppi)->ch[chtype].fd;
addr.sin_family = AF_INET;
addr.sin_port = htons(chtype == PP_NP_GEN
? PP_GEN_PORT : PP_EVT_PORT);
addr.sin_addr.s_addr = NP(ppi)->mcast_addr;
if (drop)
addr.sin_port = 3200;
ret = sendto(fd, pkt, len, 0, (struct sockaddr *)&addr,
sizeof(struct sockaddr_in));
poll_tx_timestamp(ppi, pkt, len, s, fd, t);
if (drop) /* like above: skil messages about timestamps */
break;
if (drop) /* like above: skil messages about timestamps */
goto drop_msg;
if (pp_diag_allow(ppi, frames, 2))
dump_payloadpkt("send: ", pkt, len, t);
pp_diag(ppi, time, 1, "send stamp: (correct %i) %9li.%09li\n",
t->correct, (long)t->seconds,
(long)t->nanoseconds);
return ret;
case PPSI_PROTO_VLAN:
/* FIXME */
default:
return -1;
}
if (pp_diag_allow(ppi, frames, 2))
dump_payloadpkt("send: ", pkt, len, t);
pp_diag(ppi, time, 1, "send stamp: (correct %i) %9li.%09li\n",
t->correct, (long)t->seconds,
(long)t->nanoseconds);
drop_msg:
if (drop)
pp_diag(ppi, frames, 1, "Drop sent frame\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment