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