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

Reply via email to