commit ea9c14d9ab10d1070a8d3c032e64bb946a279a02 Author: Chris Leech Date: Thu Nov 30 12:05:28 2017 -0800 vlan setting sync for be2iscsi diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c index b30518a293db..f269fc406a13 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, @@ -2319,6 +2402,8 @@ static int exec_iface_op(int op, int do_show, int info_level, struct host_info hinfo; struct node_rec *rec = NULL; int rc = 0; + LIST_HEAD(vlan_params); + struct iscsi_transport *t; switch (op) { case OP_NEW: @@ -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);