Patchwork [Open-FCoE,1/2] fipvlan: Add vn2vn support

login
register
mail settings
Submitter Mark Rustad
Date May 17, 2013, 6:51 p.m.
Message ID <20130517185101.12840.75967.stgit@host1-mdrustad.localdomain>
Download mbox | patch
Permalink /patch/47/
State Accepted
Headers show

Comments

Mark Rustad - May 17, 2013, 6:51 p.m.
Add a -m/--mode option that can be used to do either
fabric (default) VLAN discovery or vn2vn VLAN discovery.
It should be easy to modify this code to have an "auto"
mode that could concurrently do both discoveries, but
leaving that for after this code is tested.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Jack Morgan<jack.morgan@intel.com>
---
 fipvlan.c |  149 +++++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 111 insertions(+), 38 deletions(-)

Patch

diff --git a/fipvlan.c b/fipvlan.c
index edefe2f..ecce311 100644
--- a/fipvlan.c
+++ b/fipvlan.c
@@ -65,6 +65,7 @@  struct {
 	bool automode;
 	bool create;
 	bool start;
+	bool vn2vn;
 	bool debug;
 	int link_retry;
 	char suffix[256];
@@ -73,6 +74,7 @@  struct {
 	.namec = 0,
 	.automode = false,
 	.create = false,
+	.vn2vn = false,
 	.debug = false,
 	.link_retry = 20,
 	.suffix = "",
@@ -153,12 +155,14 @@  struct fcf {
 };
 
 struct fcf_list_head fcfs = TAILQ_HEAD_INITIALIZER(fcfs);
+static struct fcf_list_head vn2vns = TAILQ_HEAD_INITIALIZER(vn2vns);
 
-struct fcf *lookup_fcf(int ifindex, uint16_t vlan, unsigned char *mac)
+static struct fcf *lookup_fcf(struct fcf_list_head *head, int ifindex,
+			      uint16_t vlan, unsigned char *mac)
 {
 	struct fcf *fcf;
 
-	TAILQ_FOREACH(fcf, &fcfs, list_node)
+	TAILQ_FOREACH(fcf, head, list_node)
 		if ((ifindex == fcf->ifindex) && (vlan == fcf->vlan) &&
 		    (memcmp(mac, fcf->mac_addr, ETHER_ADDR_LEN) == 0))
 			return fcf;
@@ -263,10 +267,12 @@  unsigned int fip_parse_tlvs(void *ptr, int len, struct fip_tlv_ptrs *tlv_ptrs)
  * fip_recv_vlan_note - parse a FIP VLAN Notification
  * @fh: FIP header, the beginning of the received FIP frame
  * @ifindex: index of interface this was received on
+ * @vn2vn: true if vn2vn notification
  */
-int fip_recv_vlan_note(struct fiphdr *fh, int ifindex)
+static int fip_recv_vlan_note(struct fiphdr *fh, int ifindex, bool vn2vn)
 {
 	struct fip_tlv_ptrs tlvs;
+	struct fcf_list_head *head;
 	struct fcf *fcf;
 	struct iff *iff;
 	uint16_t vlan;
@@ -284,13 +290,18 @@  int fip_recv_vlan_note(struct fiphdr *fh, int ifindex)
 	if ((bitmap & required_tlvs) != required_tlvs)
 		return -1;
 
+	if (vn2vn)
+		head = &vn2vns;
+	else
+		head = &fcfs;
+
 	iff = lookup_iff(ifindex, NULL);
 	if (iff)
 		iff->resp_recv = true;
 
 	for (i = 0; i < tlvs.vlanc; i++) {
 		vlan = ntohs(tlvs.vlan[i]->vlan);
-		if (lookup_fcf(ifindex, vlan, tlvs.mac->mac_addr))
+		if (lookup_fcf(head, ifindex, vlan, tlvs.mac->mac_addr))
 			continue;
 
 		fcf = malloc(sizeof(*fcf));
@@ -302,7 +313,7 @@  int fip_recv_vlan_note(struct fiphdr *fh, int ifindex)
 		fcf->ifindex = ifindex;
 		fcf->vlan = vlan;
 		memcpy(fcf->mac_addr, tlvs.mac->mac_addr, ETHER_ADDR_LEN);
-		TAILQ_INSERT_TAIL(&fcfs, fcf, list_node);
+		TAILQ_INSERT_TAIL(head, fcf, list_node);
 	}
 
 	return 0;
@@ -310,8 +321,6 @@  int fip_recv_vlan_note(struct fiphdr *fh, int ifindex)
 
 int fip_vlan_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg)
 {
-	int rc = -1;
-
 	/* We only care about VLAN Notifications */
 	if (ntohs(fh->fip_proto) != FIP_PROTO_VLAN) {
 		FIP_LOG_DBG("ignoring FIP packet, protocol %d",
@@ -321,14 +330,22 @@  int fip_vlan_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg)
 
 	switch (fh->fip_subcode) {
 	case FIP_VLAN_NOTE:
-		rc = fip_recv_vlan_note(fh, sa->sll_ifindex);
-		break;
+		if (config.vn2vn) {
+			FIP_LOG_DBG("ignoring FCF response in vn2vn mode\n");
+			return -1;
+		}
+		return fip_recv_vlan_note(fh, sa->sll_ifindex, false);
+	case FIP_VLAN_NOTE_VN2VN:
+		if (!config.vn2vn) {
+			FIP_LOG_DBG("ignoring VN2VN response in fabric mode\n");
+			return -1;
+		}
+		return fip_recv_vlan_note(fh, sa->sll_ifindex, true);
 	default:
 		FIP_LOG_DBG("ignored FIP VLAN packet with subcode %d",
 			    fh->fip_subcode);
-		break;
+		return -1;
 	}
-	return rc;
 }
 
 /**
@@ -415,7 +432,7 @@  void rtnl_recv_newlink(struct nlmsghdr *nh)
 
 /* command line arguments */
 
-#define GETOPT_STR "acdf:l:shv"
+#define GETOPT_STR "acdf:l:m:shv"
 
 static const struct option long_options[] = {
 	{ "auto", no_argument, NULL, 'a' },
@@ -424,6 +441,7 @@  static const struct option long_options[] = {
 	{ "debug", no_argument, NULL, 'd' },
 	{ "suffix", required_argument, NULL, 'f' },
 	{ "link-retry", required_argument, NULL, 'l' },
+	{ "mode", required_argument, NULL, 'm' },
 	{ "help", no_argument, NULL, 'h' },
 	{ "version", no_argument, NULL, 'v' },
 	{ NULL, 0, NULL, 0 }
@@ -440,6 +458,7 @@  static void help(int status)
 		"  -s, --start          Start FCoE login automatically\n"
 		"  -f, --suffix		Append the suffix to VLAN interface name\n"
 		"  -l, --link-retry     Number of retries for link up\n"
+		"  -m, --mode           Link mode, either fabric or vn2vn\n"
 		"  -h, --help           Display this help and exit\n"
 		"  -v, --version        Display version information and exit\n",
 		exe);
@@ -475,6 +494,17 @@  void parse_cmdline(int argc, char **argv)
 		case 'l':
 			config.link_retry = strtoul(optarg, NULL, 10);
 			break;
+		case 'm':
+			if (strcasecmp(optarg, "vn2vn") == 0)
+				config.vn2vn = true;
+			else if (strcasecmp(optarg, "fabric") == 0)
+				config.vn2vn = false;
+			else {
+				fprintf(stderr, "%s: Unknown value for mode: %s\n",
+					exe, optarg);
+				exit(1);
+			}
+			break;
 		case 'h':
 			help(0);
 			break;
@@ -506,7 +536,8 @@  int rtnl_listener_handler(struct nlmsghdr *nh, void *arg)
 	return -1;
 }
 
-void create_missing_vlans()
+static void
+create_missing_vlans_list(struct fcf_list_head *list, const char *label)
 {
 	struct fcf *fcf;
 	struct iff *real_dev, *vlan;
@@ -516,11 +547,12 @@  void create_missing_vlans()
 	if (!config.create)
 		return;
 
-	TAILQ_FOREACH(fcf, &fcfs, list_node) {
+	TAILQ_FOREACH(fcf, list, list_node) {
 		real_dev = lookup_iff(fcf->ifindex, NULL);
 		if (!real_dev) {
-			FIP_LOG_ERR(ENODEV, "lost device %d with discoved FCF?",
-				    fcf->ifindex);
+			FIP_LOG_ERR(ENODEV,
+				    "lost device %d with discovered %s?\n",
+				    fcf->ifindex, label);
 			continue;
 		}
 		if (!fcf->vlan) {
@@ -534,7 +566,7 @@  void create_missing_vlans()
 		}
 		vlan = lookup_vlan(fcf->ifindex, fcf->vlan);
 		if (vlan) {
-			FIP_LOG_DBG("VLAN %s.%d already exists as %s",
+			FIP_LOG_DBG("VLAN %s.%d already exists as %s\n",
 				    real_dev->ifname, fcf->vlan, vlan->ifname);
 			continue;
 		}
@@ -542,7 +574,7 @@  void create_missing_vlans()
 			 real_dev->ifname, fcf->vlan, config.suffix);
 		rc = vlan_create(fcf->ifindex, fcf->vlan, vlan_name);
 		if (rc < 0)
-			printf("Failed to crate VLAN device %s\n\t%s\n",
+			printf("Failed to create VLAN device %s\n\t%s\n",
 			       vlan_name, strerror(-rc));
 		else
 			printf("Created VLAN device %s\n", vlan_name);
@@ -551,11 +583,25 @@  void create_missing_vlans()
 	printf("\n");
 }
 
-int fcoe_mod_instance_start(const char *ifname)
+static void create_missing_vlans(void)
+{
+	if (!TAILQ_EMPTY(&fcfs))
+		create_missing_vlans_list(&fcfs, "FCF");
+	if (!TAILQ_EMPTY(&vn2vns))
+		create_missing_vlans_list(&vn2vns, "VN2VN");
+}
+
+static int fcoe_mod_instance_start(const char *ifname)
 {
-	enum fcoe_status ret = EFAIL;
+	enum fcoe_status ret;
+	const char *path;
 
-	ret = fcm_write_str_to_sysfs_file(FCOE_CREATE, ifname);
+	if (config.vn2vn)
+		path = FCOE_CREATE_VN2VN;
+	else
+		path = FCOE_CREATE;
+
+	ret = fcm_write_str_to_sysfs_file(path, ifname);
 	if (ret) {
 		FIP_LOG_ERRNO("Failed to open file: %s", FCOE_CREATE);
 		FIP_LOG_ERRNO("May be fcoe stack not loaded, starting"
@@ -567,9 +613,9 @@  int fcoe_mod_instance_start(const char *ifname)
 	return 0;
 }
 
-int fcoe_bus_instance_start(const char *ifname)
+static int fcoe_bus_instance_start(const char *ifname)
 {
-	enum fcoe_status ret = EFAIL;
+	enum fcoe_status ret;
 	char fchost[FCHOSTBUFLEN];
 	char ctlr[FCHOSTBUFLEN];
 
@@ -591,6 +637,14 @@  int fcoe_bus_instance_start(const char *ifname)
 		return ENOSYSFS;
 	}
 
+	if (config.vn2vn) {
+		ret = fcm_write_str_to_ctlr_attr(ctlr, FCOE_CTLR_ATTR_MODE,
+						 "vn2vn");
+		if (ret)
+			FIP_LOG_DBG("Failed to set mode interface %s\n",
+				    ifname);
+	}
+
 	ret = fcm_write_str_to_ctlr_attr(ctlr, FCOE_CTLR_ATTR_ENABLED, "1");
 	if (ret)
 		FIP_LOG_DBG("Failed to enable interface %s\n", ifname);
@@ -609,12 +663,18 @@  void determine_libfcoe_interface()
 	}
 }
 
-void start_fcoe()
+static void start_fcoe(void)
 {
+	struct fcf_list_head *head;
 	struct fcf *fcf;
 	struct iff *iff;
 
-	TAILQ_FOREACH(fcf, &fcfs, list_node) {
+	if (config.vn2vn)
+		head = &vn2vns;
+	else
+		head = &fcfs;
+
+	TAILQ_FOREACH(fcf, head, list_node) {
 		if (fcf->vlan)
 			iff = lookup_vlan(fcf->ifindex, fcf->vlan);
 		else
@@ -631,20 +691,14 @@  void start_fcoe()
 	}
 }
 
-int print_results()
+static void print_list(struct fcf_list_head *list, const char *label)
 {
 	struct iff *iff;
 	struct fcf *fcf;
 
-	if (TAILQ_EMPTY(&fcfs)) {
-		printf("No Fibre Channel Forwarders Found\n");
-		return ENODEV;
-	}
-
-	printf("Fibre Channel Forwarders Discovered\n");
-	printf("%-16.16s| %-5.5s| %-17.17s\n", "interface", "VLAN", "FCF MAC");
+	printf("%-16.16s| %-5.5s| %-17.17s\n", "interface", "VLAN", label);
 	printf("------------------------------------------\n");
-	TAILQ_FOREACH(fcf, &fcfs, list_node) {
+	TAILQ_FOREACH(fcf, list, list_node) {
 		iff = lookup_iff(fcf->ifindex, NULL);
 		printf("%-16.16s| %-5d| %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
 		       iff->ifname, fcf->vlan,
@@ -652,6 +706,23 @@  int print_results()
 		       fcf->mac_addr[3], fcf->mac_addr[4], fcf->mac_addr[5]);
 	}
 	printf("\n");
+}
+
+static int print_results(void)
+{
+	if (TAILQ_EMPTY(&fcfs) && TAILQ_EMPTY(&vn2vns)) {
+		printf("No Fibre Channel Forwarders or VN2VN Responders Found\n");
+		return ENODEV;
+	}
+
+	if (!TAILQ_EMPTY(&fcfs)) {
+		printf("Fibre Channel Forwarders Discovered\n");
+		print_list(&fcfs, "FCF MAC");
+	}
+	if (!TAILQ_EMPTY(&vn2vns)) {
+		printf("VN2VN Responders Discovered\n");
+		print_list(&vn2vns, "VN2VN MAC");
+	}
 
 	return 0;
 }
@@ -717,10 +788,12 @@  static int probe_fip_interface(struct iff *iff)
 		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);
+	if (config.vn2vn)
+		fip_send_vlan_request(iff->ps, iff->ifindex, iff->mac_addr,
+				      FIP_ALL_VN2VN);
+	else
+		fip_send_vlan_request(iff->ps, iff->ifindex, iff->mac_addr,
+				      FIP_ALL_FCF);
 	iff->req_sent = true;
 	return 0;
 }