Using a packet socket on an inactive bonding slave link should require the use of a separate socket bound to each interface. fipvlan is currently only using a single unbound socket for all interfaces.
It's working right now on 2.6.33 due to a kernel bug, but this change should make it more correct if the kernel behavior gets changed. It probably doesn't work without this change on kernels earlier than 2.6.33. Signed-off-by: Chris Leech <[email protected]> --- fipvlan.c | 99 +++++++++++++++++++++++++++++++++++++++------------------ include/fip.h | 2 + lib/fip.c | 26 +++++++++++++++ 3 files changed, 95 insertions(+), 32 deletions(-) diff --git a/fipvlan.c b/fipvlan.c index 66bfacd..432ff84 100644 --- a/fipvlan.c +++ b/fipvlan.c @@ -72,9 +72,45 @@ struct { char *exe; +static struct pollfd *pfd = NULL; +static int pfd_len = 0; + +void pfd_add(int fd) +{ + struct pollfd *npfd; + + npfd = realloc(pfd, (pfd_len + 1) * sizeof(struct pollfd)); + if (!npfd) { + perror("realloc fail"); + return; + } + pfd = npfd; + pfd[pfd_len].fd = fd; + pfd[pfd_len].events = POLLIN; + pfd_len++; +} + +void pfd_remove(int fd) +{ + struct pollfd *npfd; + int i; + + for (i = 0; i < pfd_len; i++) { + if (pfd[i].fd == fd) + break; + } + if (i == pfd_len) + return; + memmove(&pfd[i], &pfd[i+1], (--pfd_len - i) * sizeof(struct pollfd)); + npfd = realloc(pfd, pfd_len * sizeof(struct pollfd)); + if (npfd) + pfd = npfd; +} + TAILQ_HEAD(iff_list_head, iff); struct iff { + int ps; /* packet socket file descriptor */ int ifindex; int iflink; char ifname[IFNAMSIZ]; @@ -266,6 +302,7 @@ void rtnl_recv_newlink(struct nlmsghdr *nh) struct rtattr *linkinfo[__IFLA_INFO_MAX]; struct rtattr *vlan[__IFLA_VLAN_MAX]; struct iff *iff, *real_dev; + int origdev = 1; FIP_LOG_DBG("RTM_NEWLINK: ifindex %d, type %d", ifm->ifi_index, ifm->ifi_type); @@ -323,6 +360,10 @@ void rtnl_recv_newlink(struct nlmsghdr *nh) return; } } + iff->ps = fip_socket(iff->ifindex); + setsockopt(iff->ps, SOL_PACKET, PACKET_ORIGDEV, + &origdev, sizeof(origdev)); + pfd_add(iff->ps); TAILQ_INSERT_TAIL(&interfaces, iff, list_node); } @@ -495,18 +536,13 @@ void print_results() printf("\n"); } -void recv_loop(int ns, int ps, int timeout) +void recv_loop(struct pollfd *pfd, int pfd_len, int timeout) { - struct pollfd pfd[2] = { - [0].fd = ns, - [0].events = POLLIN, - [1].fd = ps, - [1].events = POLLIN, - }; + int i; int rc; while (1) { - rc = poll(pfd, ARRAY_SIZE(pfd), timeout); + rc = poll(pfd, pfd_len, timeout); FIP_LOG_DBG("return from poll %d", rc); if (rc == 0) /* timeout */ break; @@ -514,12 +550,16 @@ void recv_loop(int ns, int ps, int timeout) FIP_LOG_ERRNO("poll error"); break; } + /* pfd[0] must be the netlink socket */ if (pfd[0].revents) - rtnl_recv(ns, rtnl_listener_handler, NULL); - if (pfd[1].revents) - fip_recv(ps, fip_vlan_handler, NULL); + rtnl_recv(pfd[0].fd, rtnl_listener_handler, NULL); pfd[0].revents = 0; - pfd[1].revents = 0; + /* everything else should be FIP packet sockets */ + for (i = 1; i < pfd_len; i++) { + if (pfd[i].revents) + fip_recv(pfd[i].fd, fip_vlan_handler, NULL); + pfd[i].revents = 0; + } } } @@ -529,7 +569,7 @@ void find_interfaces(int ns) rtnl_recv(ns, rtnl_listener_handler, NULL); } -int send_vlan_requests(int ps) +int send_vlan_requests(void) { struct iff *iff; int i; @@ -544,7 +584,9 @@ int send_vlan_requests(int ps) iff->req_sent = false; continue; } - fip_send_vlan_request(ps, iff->ifindex, iff->mac_addr); + fip_send_vlan_request(iff->ps, + iff->ifindex, + iff->mac_addr); iff->req_sent = true; } } else { @@ -561,29 +603,31 @@ int send_vlan_requests(int ps) iff->req_sent = false; continue; } - fip_send_vlan_request(ps, iff->ifindex, iff->mac_addr); + fip_send_vlan_request(iff->ps, + iff->ifindex, + iff->mac_addr); iff->req_sent = true; } } return skipped; } -void do_vlan_discovery(ns, ps) +void do_vlan_discovery(void) { struct iff *iff; int retry_count = 0; int skip_retry_count = 0; int skipped = 0; retry: - skipped += send_vlan_requests(ps); + skipped += send_vlan_requests(); if (skipped && skip_retry_count++ < 30) { FIP_LOG_DBG("waiting for IFF_RUNNING [%d]\n", skip_retry_count); - recv_loop(ns, ps, 500); + recv_loop(pfd, pfd_len, 500); skipped = 0; retry_count = 0; goto retry; } - recv_loop(ns, ps, 200); + recv_loop(pfd, pfd_len, 200); TAILQ_FOREACH(iff, &interfaces, list_node) /* if we did not receive a response, retry */ if (iff->req_sent && !iff->resp_recv && retry_count++ < 10) { @@ -594,9 +638,8 @@ retry: int main(int argc, char **argv) { - int ps, ns; + int ns; int rc = 0; - int origdev = 1; exe = strrchr(argv[0], '/'); if (exe) @@ -609,27 +652,21 @@ int main(int argc, char **argv) sa_log_flags = 0; enable_debug_log(0); - ps = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_FIP)); - if (ps < 0) { - rc = ps; - goto ps_err; - } - setsockopt(ps, SOL_PACKET, PACKET_ORIGDEV, &origdev, sizeof(origdev)); ns = rtnl_socket(); if (ns < 0) { rc = ns; goto ns_err; } + pfd_add(ns); find_interfaces(ns); if (TAILQ_EMPTY(&interfaces)) { FIP_LOG_ERR(ENODEV, "no interfaces to perform discovery on"); - close(ps); exit(1); } - do_vlan_discovery(ns, ps); + do_vlan_discovery(); print_results(); if (config.create) { @@ -638,14 +675,12 @@ int main(int argc, char **argv) * need to listen for the RTM_NETLINK messages * about the new VLAN devices */ - recv_loop(ns, ps, 500); + recv_loop(pfd, pfd_len, 500); } if (config.start) start_fcoe(); close(ns); ns_err: - close(ps); -ps_err: exit(rc); } diff --git a/include/fip.h b/include/fip.h index 5f39763..ae8a365 100644 --- a/include/fip.h +++ b/include/fip.h @@ -129,6 +129,8 @@ struct fip_tlv_vlan { /* libutil / fip.c functionality */ +int fip_socket(int ifindex); + /* FIP message handler, passed into fip_recv */ typedef int fip_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg); diff --git a/lib/fip.c b/lib/fip.c index b0bf07d..77aa067 100644 --- a/lib/fip.c +++ b/lib/fip.c @@ -50,6 +50,32 @@ #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) /** + * fip_socket - create and bind a packet socket for FIP + */ +int fip_socket(int ifindex) +{ + struct sockaddr_ll sa = { + .sll_family = AF_PACKET, + .sll_protocol = htons(ETH_P_FIP), + .sll_ifindex = ifindex, + }; + int s; + int rc; + + s = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_FIP)); + if (s < 0) + return s; + + rc = bind(s, (struct sockaddr *) &sa, sizeof(sa)); + if (rc < 0) { + close(s); + return rc; + } + + return s; +} + +/** * fip_send_vlan_request - send a FIP VLAN request * @s: ETH_P_FIP packet socket to send on * @ifindex: network interface index to send on _______________________________________________ devel mailing list [email protected] http://www.open-fcoe.org/mailman/listinfo/devel
