Implement support for VN2VN FIP VLAN discovery as described in T11 document 12-218v1.
Signed-off-by: Mark Rustad <[email protected]> Tested-by: Jack Morgan <[email protected]> --- fcoemon.c | 45 +++++++++++++++++++----- fipvlan.c | 105 ++++++++++++++++++++++----------------------------------- include/fip.h | 18 +++++++++- lib/fip.c | 14 +++++--- 4 files changed, 101 insertions(+), 81 deletions(-) diff --git a/fcoemon.c b/fcoemon.c index 982c4a9..ab7bbe2 100644 --- a/fcoemon.c +++ b/fcoemon.c @@ -565,10 +565,8 @@ static int fcm_read_config_files(void) } /* if not found, default to "fabric" */ next->mode = FCOE_MODE_FABRIC; - if (!strncasecmp(val, "vn2vn", 5) && rc == 1) { + if (!strncasecmp(val, "vn2vn", 5) && rc == 1) next->mode = FCOE_MODE_VN2VN; - next->auto_vlan = 0; /* TODO: Until we can do it */ - } fclose(fp); @@ -892,13 +890,20 @@ static int fcm_link_init(void) static struct fcoe_port * fcm_port_create(char *ifname, enum clif_flags flags, int cmd); -struct fcoe_port *fcm_new_vlan(int ifindex, int vid) +struct fcoe_port *fcm_new_vlan(int ifindex, int vid, bool vn2vn) { char real_name[IFNAMSIZ]; char vlan_name[IFNAMSIZ]; struct fcoe_port *p; + static const int flags[] = { + [false] = CLIF_FLAGS_FABRIC, + [true] = CLIF_FLAGS_VN2VN, + }; - FCM_LOG_DBG("Auto VLAN Found FCF on VID %d\n", vid); + if (vn2vn) + FCM_LOG_DBG("Auto VLAN found vn2vn on VID %d\n", vid); + else + FCM_LOG_DBG("Auto VLAN Found FCF on VID %d\n", vid); if (rtnl_find_vlan(ifindex, vid, vlan_name)) { rtnl_get_linkname(ifindex, real_name); @@ -909,7 +914,7 @@ struct fcoe_port *fcm_new_vlan(int ifindex, int vid) p = fcm_find_fcoe_port(vlan_name, FCP_CFG_IFNAME); if (p && !p->fcoe_enable) return p; - p = fcm_port_create(vlan_name, CLIF_FLAGS_NONE, FCP_ACTIVATE_IF); + p = fcm_port_create(vlan_name, flags[vn2vn], FCP_ACTIVATE_IF); p->auto_created = 1; return p; } @@ -924,6 +929,7 @@ int fcm_vlan_disc_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg) struct fcoe_port *p = arg; struct fcoe_port *vp; int desc_mask = 0; + bool vn2vn = false; enum { VALID_MAC = 1, @@ -933,9 +939,17 @@ int fcm_vlan_disc_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg) if (ntohs(fh->fip_proto) != FIP_PROTO_VLAN) return -1; - if (fh->fip_subcode != FIP_VLAN_NOTE) + if (fh->fip_subcode == FIP_VLAN_NOTE_VN2VN && + (!p->auto_vlan || p->mode != FCOE_MODE_VN2VN)) return -1; + if (fh->fip_subcode != FIP_VLAN_NOTE && + fh->fip_subcode != FIP_VLAN_NOTE_VN2VN) + return -1; + + if (fh->fip_subcode == FIP_VLAN_NOTE_VN2VN) + vn2vn = true; + while (len > 0) { switch (tlv->tlv_type) { case FIP_TLV_MAC_ADDR: @@ -955,7 +969,7 @@ int fcm_vlan_disc_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg) vid = ntohs(((struct fip_tlv_vlan *)tlv)->vlan); if (vid) { - vp = fcm_new_vlan(sa->sll_ifindex, vid); + vp = fcm_new_vlan(sa->sll_ifindex, vid, vn2vn); vp->dcb_required = p->dcb_required; } else { /* We received a 0 vlan id. Activate the @@ -2710,13 +2724,24 @@ err_out: return ret; } +static void fcm_send_fip_request(const struct fcoe_port *p) +{ + int dest; + + if (p->mode == FCOE_MODE_VN2VN) + dest = FIP_ALL_VN2VN; + else + dest = FIP_ALL_FCF; + fip_send_vlan_request(p->fip_socket, p->ifindex, p->mac, dest); +} + void fcm_vlan_disc_timeout(void *arg) { struct fcoe_port *p = arg; FCM_LOG_DBG("%s: VLAN discovery TIMEOUT [%d]", p->ifname, p->vlan_disc_count); p->vlan_disc_count++; - fip_send_vlan_request(p->fip_socket, p->ifindex, p->mac); + fcm_send_fip_request(p); sa_timer_set(&p->vlan_disc_timer, FCM_VLAN_DISC_TIMEOUT); } @@ -2730,7 +2755,7 @@ int fcm_start_vlan_disc(struct fcoe_port *p) p->fip_socket = s; } p->vlan_disc_count = 1; - fip_send_vlan_request(p->fip_socket, p->ifindex, p->mac); + fcm_send_fip_request(p); sa_timer_set(&p->vlan_disc_timer, FCM_VLAN_DISC_TIMEOUT); return 0; } diff --git a/fipvlan.c b/fipvlan.c index 882ebbc..98e7a22 100644 --- a/fipvlan.c +++ b/fipvlan.c @@ -687,48 +687,53 @@ void find_interfaces(int ns) rtnl_recv(ns, rtnl_listener_handler, NULL); } +static int probe_fip_interface(struct iff *iff) +{ + int origdev = 1; + + if (iff->resp_recv) + return 0; + if (!iff->running) { + if (iff->linkup_sent) { + FIP_LOG_DBG("if %d not running, waiting for link up", + iff->ifindex); + } else { + FIP_LOG_DBG("if %d not running, starting", + iff->ifindex); + rtnl_set_iff_up(iff->ifindex, NULL); + iff->linkup_sent = true; + } + iff->req_sent = false; + return 1; + } + if (iff->req_sent) + return 0; + + if (!iff->fip_ready) { + iff->ps = fip_socket(iff->ifindex); + setsockopt(iff->ps, SOL_PACKET, PACKET_ORIGDEV, + &origdev, sizeof(origdev)); + pfd_add(iff->ps); + iff->fip_ready = true; + } + + fip_send_vlan_request(iff->ps, iff->ifindex, iff->mac_addr, + FIP_ALL_FCF); + fip_send_vlan_request(iff->ps, iff->ifindex, iff->mac_addr, + FIP_ALL_VN2VN); + iff->req_sent = true; + return 0; +} + int send_vlan_requests(void) { struct iff *iff; int i; int skipped = 0; - int origdev = 1; if (config.automode) { TAILQ_FOREACH(iff, &interfaces, list_node) { - if (iff->resp_recv) - continue; - if (!iff->running) { - if (iff->linkup_sent) { - FIP_LOG_DBG("if %d not running, " - "waiting for link up", - iff->ifindex); - } else { - FIP_LOG_DBG("if %d not running, " - "starting", - iff->ifindex); - rtnl_set_iff_up(iff->ifindex, NULL); - iff->linkup_sent = true; - } - skipped++; - iff->req_sent = false; - continue; - } - if (iff->req_sent) - continue; - - if (!iff->fip_ready) { - iff->ps = fip_socket(iff->ifindex); - setsockopt(iff->ps, SOL_PACKET, PACKET_ORIGDEV, - &origdev, sizeof(origdev)); - pfd_add(iff->ps); - iff->fip_ready = true; - } - - fip_send_vlan_request(iff->ps, - iff->ifindex, - iff->mac_addr); - iff->req_sent = true; + skipped += probe_fip_interface(iff); } } else { for (i = 0; i < config.namec; i++) { @@ -737,37 +742,7 @@ int send_vlan_requests(void) skipped++; continue; } - if (iff->resp_recv) - continue; - if (!iff->running) { - if (iff->linkup_sent) { - FIP_LOG_DBG("if %d not running, " - "waiting for link up", - iff->ifindex); - } else { - FIP_LOG_DBG("if %d not running, " - "starting", - iff->ifindex); - rtnl_set_iff_up(iff->ifindex, NULL); - iff->linkup_sent = true; - } - skipped++; - iff->req_sent = false; - continue; - } - - if (!iff->fip_ready) { - iff->ps = fip_socket(iff->ifindex); - setsockopt(iff->ps, SOL_PACKET, PACKET_ORIGDEV, - &origdev, sizeof(origdev)); - pfd_add(iff->ps); - iff->fip_ready = true; - } - - fip_send_vlan_request(iff->ps, - iff->ifindex, - iff->mac_addr); - iff->req_sent = true; + skipped += probe_fip_interface(iff); } } return skipped; diff --git a/include/fip.h b/include/fip.h index 226301e..7dc2463 100644 --- a/include/fip.h +++ b/include/fip.h @@ -31,6 +31,17 @@ #define FIP_ALL_FCOE_MACS { 0x01, 0x10, 0x18, 0x01, 0x00, 0x00 } #define FIP_ALL_ENODE_MACS { 0x01, 0x10, 0x18, 0x01, 0x00, 0x01 } #define FIP_ALL_FCF_MACS { 0x01, 0x10, 0x18, 0x01, 0x00, 0x02 } +#define FIP_ALL_VN2VN_MACS { 0x01, 0x10, 0x18, 0x01, 0x00, 0x04 } + +/* The following values are chosen to match the last byte of + * the corresponding FIP multicast MAC address. + */ +enum fip_multi { + FIP_ALL_FCOE = 0, + FIP_ALL_ENODE = 1, + FIP_ALL_FCF = 2, + FIP_ALL_VN2VN = 4, +}; struct fiphdr { uint8_t fip_version; /* version, upper 4 bits only */ @@ -68,6 +79,7 @@ struct fiphdr { #define FIP_PROTO_VLAN 4 #define FIP_VLAN_REQ 1 #define FIP_VLAN_NOTE 2 +#define FIP_VLAN_NOTE_VN2VN 3 struct fip_tlv_hdr { uint8_t tlv_type; @@ -147,9 +159,11 @@ int fip_recv(int s, fip_handler *fn, void *arg); * @s: ETH_P_FIP packet socket to send on * @ifindex: network interface index to send on * @mac: mac address of the netif + * @dest: destination selector * - * Note: sends to FIP_ALL_FCF_MACS + * Note: sends to destination selected by @dest */ -ssize_t fip_send_vlan_request(int s, int ifindex, unsigned char *mac); +ssize_t fip_send_vlan_request(int s, int ifindex, const unsigned char *mac, + enum fip_multi); #endif /* FIP_H */ diff --git a/lib/fip.c b/lib/fip.c index cf730ee..1acc388 100644 --- a/lib/fip.c +++ b/lib/fip.c @@ -118,16 +118,19 @@ static void fip_socket_sanmac(int s, int ifindex, int add) * @ifindex: network interface index to send on * @mac: mac address of the sending network interface * @eh: buffer for ether header + * @dest: destination selector * * Note: assuming no VLAN */ -static void fip_ethhdr(int ifindex, unsigned char *mac, struct ethhdr *eh) +static void fip_ethhdr(int ifindex, const unsigned char *mac, struct ethhdr *eh, + enum fip_multi multi) { unsigned char smac[ETHER_ADDR_LEN]; unsigned char dmac[ETHER_ADDR_LEN] = FIP_ALL_FCF_MACS; if (fip_get_sanmac(ifindex, smac)) memcpy(smac, mac, ETHER_ADDR_LEN); + dmac[ETHER_ADDR_LEN - 1] = multi; eh->h_proto = htons(ETH_P_FIP); memcpy(eh->h_source, smac, ETHER_ADDR_LEN); memcpy(eh->h_dest, dmac, ETHER_ADDR_LEN); @@ -196,10 +199,12 @@ int fip_socket(int ifindex) * @s: ETH_P_FIP packet socket to send on * @ifindex: network interface index to send on * @mac: mac address of the sending network interface + * @dest: destination selector * - * Note: sends to FIP_ALL_FCF_MACS + * Note: sends to address selected by @dest */ -ssize_t fip_send_vlan_request(int s, int ifindex, unsigned char *mac) +ssize_t fip_send_vlan_request(int s, int ifindex, const unsigned char *mac, + enum fip_multi dest) { struct sockaddr_ll sa = { .sll_family = AF_PACKET, @@ -239,7 +244,8 @@ ssize_t fip_send_vlan_request(int s, int ifindex, unsigned char *mac) }; int rc; - fip_ethhdr(ifindex, mac, &eh); + fip_ethhdr(ifindex, mac, &eh, dest); + sa.sll_addr[ETHER_ADDR_LEN - 1] = dest; memcpy(tlvs.mac.mac_addr, eh.h_source, ETHER_ADDR_LEN); FIP_LOG_DBG("sending FIP VLAN request"); rc = sendmsg(s, &msg, 0); _______________________________________________ fcoe-devel mailing list [email protected] http://lists.open-fcoe.org/mailman/listinfo/fcoe-devel
