Blame SOURCES/open-iscsi-2.0.876-41-vlan-setting-sync-across-ipv4-ipv6-for-be2iscsi.patch

36b27b
From 2cee7f4a011619480c83d8279fe5d15de6e37ea8 Mon Sep 17 00:00:00 2001
36b27b
From: Chris Leech <cleech@redhat.com>
36b27b
Date: Fri, 22 Jun 2018 12:25:05 -0700
36b27b
Subject: [PATCH 1/1] vlan setting sync across ipv4/ipv6 for be2iscsi
7bf295
36b27b
be2iscsi exports two ifaces per host port for ipv4 and ipv6 network
36b27b
configurations. But, they need to have the same link level configuration
36b27b
including vlan settings. If vlan setting are modified in only one iface
36b27b
record, then whichever record is applied last (filesystem dependant I
36b27b
think) will take effect and things may not work.
36b27b
36b27b
This change to iscsiadm applies vlan updates to all records with
36b27b
matching MAC addresses if a flag is set on the transport.
36b27b
The new transport flag is only set for be2iscsi.
36b27b
---
36b27b
 usr/iscsiadm.c  | 132 ++++++++++++++++++++++++++++++++++++++++++++------------
36b27b
 usr/transport.c |   1 +
36b27b
 usr/transport.h |   3 ++
36b27b
 3 files changed, 108 insertions(+), 28 deletions(-)
7bf295
7bf295
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
36b27b
index 6245e89d46cb..9083132942e2 100644
7bf295
--- a/usr/iscsiadm.c
7bf295
+++ b/usr/iscsiadm.c
7bf295
@@ -2311,6 +2311,89 @@ static int verify_iface_params(struct list_head *params, struct node_rec *rec)
7bf295
 	return 0;
7bf295
 }
7bf295
 
7bf295
+static int iface_param_update(struct iface_rec *iface, struct list_head *params)
7bf295
+{
7bf295
+	struct node_rec *rec;
7bf295
+	int rc = 0;
7bf295
+
7bf295
+	rec = idbm_create_rec(NULL, -1, NULL, -1, iface, 1);
7bf295
+	if (!rec) {
7bf295
+		rc = ISCSI_ERR_INVAL;
7bf295
+		goto update_fail;
7bf295
+	}
7bf295
+
7bf295
+	if (iscsi_check_for_running_session(rec))
7bf295
+		log_warning("Updating iface while iscsi sessions "
7bf295
+			    "are using it. You must logout the running "
7bf295
+			    "sessions then log back in for the "
7bf295
+			    "new settings to take affect.");
7bf295
+
7bf295
+	rc = verify_iface_params(params, rec);
7bf295
+	if (rc)
7bf295
+		goto update_fail;
7bf295
+
7bf295
+	rc = iface_conf_update(params, &rec->iface);
7bf295
+	if (rc)
7bf295
+		goto update_fail;
7bf295
+
7bf295
+	rc = __for_each_matched_rec(0, rec, params, idbm_node_set_param);
7bf295
+	if (rc == ISCSI_ERR_NO_OBJS_FOUND)
7bf295
+		rc = 0;
7bf295
+	else if (rc)
7bf295
+		goto update_fail;
7bf295
+
7bf295
+	printf("%s updated.\n", iface->name);
7bf295
+	free(rec);
7bf295
+	return rc;
7bf295
+
7bf295
+update_fail:
7bf295
+	log_error("Could not update iface %s: %s",
7bf295
+		  iface->name, iscsi_err_to_str(rc));
7bf295
+	free(rec);
7bf295
+	return rc;
7bf295
+}
7bf295
+
7bf295
+struct iface_param_sync {
7bf295
+	struct iface_rec *primary;
7bf295
+	struct list_head *params;
7bf295
+	int count;
7bf295
+};
7bf295
+
7bf295
+static int update_sync_params(void *data, struct iface_rec *iface)
7bf295
+{
7bf295
+	struct iface_param_sync *iface_params = data;
7bf295
+	struct iface_rec *primary = iface_params->primary;
7bf295
+	struct list_head *params = iface_params->params;
7bf295
+
7bf295
+	if ((strcmp(primary->transport_name, iface->transport_name)) ||
7bf295
+	    (strcmp(primary->hwaddress, iface->hwaddress)) ||
7bf295
+	    (primary->iface_num != iface->iface_num))
7bf295
+		return 0;
7bf295
+
7bf295
+	return iface_param_update(iface, params);
7bf295
+}
7bf295
+
7bf295
+static int split_vlan_params(struct list_head *params, struct list_head *vlan_params)
7bf295
+{
7bf295
+	struct user_param *param, *tmp;
7bf295
+
7bf295
+	list_for_each_entry_safe(param, tmp, params, list) {
7bf295
+		if (!strncmp(param->name, "iface.vlan", 10)) {
7bf295
+			list_move_tail(&param->list, vlan_params);
7bf295
+		}
7bf295
+	}
7bf295
+	return 0;
7bf295
+}
7bf295
+
7bf295
+static inline void list_splice_tail(struct list_head *list, struct list_head *head)
7bf295
+{
7bf295
+	list->prev->next = head;
7bf295
+	list->next->prev = head->prev;
7bf295
+	head->prev->next = list->next;
7bf295
+	head->prev = list->prev;
7bf295
+	INIT_LIST_HEAD(list);
7bf295
+}
7bf295
+
7bf295
 /* TODO: merge iter helpers and clean them up, so we can use them here */
7bf295
 static int exec_iface_op(int op, int do_show, int info_level,
7bf295
 			 struct iface_rec *iface, uint64_t host_no,
36b27b
@@ -2320,6 +2403,8 @@ static int exec_iface_op(int op, int do_show, int info_level,
7bf295
 	struct node_rec *rec = NULL;
7bf295
 	int rc = 0;
36b27b
 
7bf295
+	LIST_HEAD(vlan_params);
7bf295
+	struct iscsi_transport *t;
7bf295
 	switch (op) {
7bf295
 	case OP_NEW:
36b27b
 		if (!iface) {
7bf295
@@ -2381,36 +2466,27 @@ delete_fail:
7bf295
 		rec = idbm_create_rec(NULL, -1, NULL, -1, iface, 1);
7bf295
 		if (!rec) {
7bf295
 			rc = ISCSI_ERR_INVAL;
7bf295
-			goto update_fail;
7bf295
+			break;
7bf295
 		}
7bf295
-
7bf295
-		if (iscsi_check_for_running_session(rec))
7bf295
-			log_warning("Updating iface while iscsi sessions "
7bf295
-				    "are using it. You must logout the running "
7bf295
-				    "sessions then log back in for the "
7bf295
-				    "new settings to take affect.");
7bf295
-
7bf295
-		rc = verify_iface_params(params, rec);
7bf295
-		if (rc)
7bf295
+		t = iscsi_sysfs_get_transport_by_name(rec->iface.transport_name);
7bf295
+		if (!t) {
7bf295
+			log_error("Cound not locate transport for iface %s", iface->name);
7bf295
+			rc = ISCSI_ERR_INVAL;
7bf295
 			break;
7bf295
-
7bf295
-		/* pass rec's iface because it has the db values */
7bf295
-		rc = iface_conf_update(params, &rec->iface);
7bf295
-		if (rc)
7bf295
-			goto update_fail;
7bf295
-
7bf295
-		rc = __for_each_matched_rec(0, rec, params,
7bf295
-					    idbm_node_set_param);
7bf295
-		if (rc == ISCSI_ERR_NO_OBJS_FOUND)
7bf295
-			rc = 0;
7bf295
-		else if (rc)
7bf295
-			goto update_fail;
7bf295
-
7bf295
-		printf("%s updated.\n", iface->name);
7bf295
-		break;
7bf295
-update_fail:
7bf295
-		log_error("Could not update iface %s: %s",
7bf295
-			  iface->name, iscsi_err_to_str(rc));
7bf295
+		}
7bf295
+		if (t->template->sync_vlan_settings) {
7bf295
+			/* sync shared vlan settings across ifaces */
7bf295
+			int nr_found = 0;
7bf295
+			struct iface_param_sync sync_params = {
7bf295
+				.primary = &rec->iface,
7bf295
+				.params = &vlan_params,
7bf295
+				.count = 0,
7bf295
+			};
7bf295
+			split_vlan_params(params, &vlan_params);
7bf295
+			iface_for_each_iface(&sync_params, 1, &nr_found, update_sync_params);
7bf295
+		}
7bf295
+		iface_param_update(&rec->iface, params);
7bf295
+		list_splice_tail(&vlan_params, params);
7bf295
 		break;
7bf295
 	case OP_APPLY:
7bf295
 		if (!iface) {
7bf295
diff --git a/usr/transport.c b/usr/transport.c
7bf295
index 3b7a00a2245e..35a8ccd4a400 100644
7bf295
--- a/usr/transport.c
7bf295
+++ b/usr/transport.c
7bf295
@@ -91,6 +91,7 @@ struct iscsi_transport_template bnx2i = {
7bf295
 struct iscsi_transport_template be2iscsi = {
7bf295
 	.name		= "be2iscsi",
7bf295
         .bind_ep_required = 1,
7bf295
+	.sync_vlan_settings = 1,
7bf295
 	.create_conn	= be2iscsi_create_conn,
7bf295
 	.ep_connect	= ktransport_ep_connect,
7bf295
 	.ep_poll	= ktransport_ep_poll,
7bf295
diff --git a/usr/transport.h b/usr/transport.h
7bf295
index b67776b47288..07027564e46b 100644
7bf295
--- a/usr/transport.h
7bf295
+++ b/usr/transport.h
7bf295
@@ -40,6 +40,9 @@ struct iscsi_transport_template {
7bf295
 	uint8_t use_boot_info;
7bf295
         uint8_t bind_ep_required;
7bf295
 	uint8_t no_netdev;
7bf295
+	/* be2iscsi has a single host vlan setting,
7bf295
+	 * but uses 2 ifaces for ipv4 and ipv6 settings; keep them in sync */
7bf295
+	uint8_t sync_vlan_settings;
7bf295
 	int (*ep_connect) (struct iscsi_conn *conn, int non_blocking);
7bf295
 	int (*ep_poll) (struct iscsi_conn *conn, int timeout_ms);
7bf295
 	void (*ep_disconnect) (struct iscsi_conn *conn);
36b27b
-- 
36b27b
2.14.4
36b27b