Patchwork [Open-FCoE,06/10] fip: Add VN2VN FIP VLAN discovery support

login
register
mail settings
Submitter Mark Rustad
Date March 19, 2013, 11:33 p.m.
Message ID <20130319233349.3241.42054.stgit@host1-mdrustad.localdomain>
Download mbox | patch
Permalink /patch/26/
State Accepted
Headers show

Comments

Mark Rustad - March 19, 2013, 11:33 p.m.
Implement support for VN2VN FIP VLAN discovery as described in
T11 document 12-218v1.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Jack Morgan <jack.morgan@intel.com>
---

 fcoemon.c     |   45 +++++++++++++++++++-----
 fipvlan.c     |  105 ++++++++++++++++++++++-----------------------------------
 include/fip.h |   18 +++++++++-
 lib/fip.c     |   14 +++++---
 4 files changed, 101 insertions(+), 81 deletions(-)

Patch

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);