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

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