Date: Mon, 28 May 2018 20:05:52 GMT From: sduo@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r337258 - in soc2018/sduo/head/sys: dev/vale_vlan modules/vale_vlan net Message-ID: <201805282005.w4SK5qVE018660@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sduo Date: Mon May 28 20:05:50 2018 New Revision: 337258 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=337258 Log: VLAN can now be created, and modified, through system calls. sys/net/vale_vlan_user.h contains the data structures passed between user and kernel space. Added: soc2018/sduo/head/sys/net/vale_vlan_user.h Modified: soc2018/sduo/head/sys/dev/vale_vlan/vale_vlan.c soc2018/sduo/head/sys/dev/vale_vlan/vale_vlan_freebsd.c soc2018/sduo/head/sys/dev/vale_vlan/vale_vlan_kern.h soc2018/sduo/head/sys/modules/vale_vlan/Makefile Modified: soc2018/sduo/head/sys/dev/vale_vlan/vale_vlan.c ============================================================================== --- soc2018/sduo/head/sys/dev/vale_vlan/vale_vlan.c Mon May 28 19:59:53 2018 (r337257) +++ soc2018/sduo/head/sys/dev/vale_vlan/vale_vlan.c Mon May 28 20:05:50 2018 (r337258) @@ -146,8 +146,6 @@ -#define MAX_VLAN_ID 4096 - struct vlan_lookup_data { uint32_t trunk_port; uint16_t port_to_vlan[NM_BDG_MAXPORTS]; @@ -156,6 +154,95 @@ +/* must be called with GLOBAL_LOCK */ +static void +initialize_lookup_data(struct vlan_lookup_data *l_data) +{ + int i; + + l_data->trunk_port = NM_BDG_NOPORT; + for (i = 0; i < NM_BDG_MAXPORTS; ++i) { + l_data->port_to_vlan[i] = 0x000; + } + for (i = 0; i < MAX_VLAN_ID; ++i) { + l_data->vlan_to_port[i] = NM_BDG_NOPORT; + } +} + + + +struct port_elem { + struct port port_desc; + vv_list_entry(port_elem) list; +}; + + + +/* for each vlan conf there is only one 'modified bridge', + * therefore we can store a lookup data structure directly inside + * the struct which describes the configuration + */ +struct vale_vlan_conf { + struct vlan_lookup_data l_data; + char conf_name[NETMAP_REQ_IFNAMSIZ]; + void *vlan_bdg_auth_tokens[MAX_VLAN_ID]; + void *mod_bdg_auth_token; + uint32_t number_of_ports[MAX_VLAN_ID]; + vv_list_declare(list_head, port_elem) port_list; +}; + + + +/* there is one 'vlan_id bridge' with a specific vlan_id per configuration, + * therefore we only need the configuration name and vlan_id to create + * a unique bridge name + */ +static inline void +get_vlan_bdg_name(char *bridge_name, size_t len, const char *conf_name, + uint16_t vlan_id) +{ + + snprintf(bridge_name, len, "valeV%d%s:", vlan_id, conf_name); +} + + + +static inline void +get_ap_name(char *port_name, size_t len, const char *conf_name, + uint16_t vlan_id) +{ + + snprintf(port_name, len, "%sAP%d", conf_name, vlan_id); +} + + + +/* there is one 'modified bridge' per configuration, therefore we + * only need the configuration name to create a unique bridge name + */ +static inline void +get_modified_bdg_name(char *bridge_name, size_t len, const char *conf_name) +{ + + snprintf(bridge_name, len, "valeV%sTP:", conf_name); +} + + + +static void +initialize_conf(struct vale_vlan_conf *conf) +{ + + initialize_lookup_data(&(conf->l_data)); + conf->conf_name[0] = '\0'; + bzero(conf->vlan_bdg_auth_tokens, sizeof(conf->vlan_bdg_auth_tokens)); + conf->mod_bdg_auth_token = NULL; + bzero(conf->number_of_ports, sizeof(conf->number_of_ports)); + vv_list_head_init(&conf->port_list); +} + + + static uint32_t vlan_lookup(struct nm_bdg_fwd *ft, uint8_t *dst_ring, struct netmap_vp_adapter *vpna, void *lookup_data) @@ -200,19 +287,240 @@ -/* must be called with GLOBAL_LOCK */ -static void -initialize_lookup_data(struct vlan_lookup_data *l_data) +static inline int +modify_bdg(struct vale_vlan_conf *conf, const char *bdg_name) +{ + + D("Trying to modify bdg '%s' for conf '%s'", bdg_name, conf->conf_name); + return netmap_bdg_regops(bdg_name, &vlan_ops, &conf->l_data, + conf->mod_bdg_auth_token); +} + + + +static inline int +reset_bdg(struct vale_vlan_conf *conf, const char *bdg_name) +{ + + D("Trying to reset bdg '%s' for conf '%s'", bdg_name, conf->conf_name); + return netmap_bdg_regops(bdg_name, NULL, NULL, + conf->mod_bdg_auth_token); +} + + + +#define MAX_VLAN_CONFS 4 +/* used to access currently active vlan confs */ +static uint16_t vlan_conf_index[MAX_VLAN_CONFS]; +static struct vale_vlan_conf vlan_confs[MAX_VLAN_CONFS]; +static uint16_t active_vlan_conf = 0; + + + +/* Fails if conf alredy exists or we're out of space */ +static int +vale_vlan_create_conf(const char *conf_name, uint16_t *conf_index) { + uint16_t free_conf = MAX_VLAN_CONFS; + char modified_bdg_name[IF_NAMESIZE]; + struct vale_vlan_conf *conf = NULL; + void *auth_token = NULL; + int ret = 0; int i; - l_data->trunk_port = NM_BDG_NOPORT; - for (i = 0; i < NM_BDG_MAXPORTS; ++i) { - l_data->port_to_vlan[i] = 0x000; + if (active_vlan_conf == MAX_VLAN_CONFS) { + nm_prinf("vale_vlan: maximum number of" + "configurations reached\n"); + return ENOMEM; + } + + for (i = 0; i < MAX_VLAN_CONFS; ++i) { + if (strcmp(vlan_confs[i].conf_name, conf_name) == 0) { + nm_prinf("vale_vlan: a configuration named" + "'%s' alredy exists\n", conf_name); + return EEXIST; + } else if (vlan_confs[i].conf_name[0] == '\0') { + /* a free slot is represented by an empty conf_name */ + free_conf = i; + } + } + + /* create bridge in exclusive mode */ + get_modified_bdg_name(modified_bdg_name, sizeof(modified_bdg_name), + conf_name); + auth_token = netmap_bdg_create(modified_bdg_name, &ret); + if (auth_token == NULL || ret != 0) { + D("Error %d during bridge '%s' creation", + ret, modified_bdg_name); + return ret; + } + + vlan_conf_index[active_vlan_conf++] = free_conf; + conf = &vlan_confs[free_conf]; + initialize_conf(conf); + strncpy(conf->conf_name, conf_name, sizeof(conf->conf_name)); + conf->mod_bdg_auth_token = auth_token; + *conf_index = free_conf; + + ret = modify_bdg(conf, modified_bdg_name); + if (ret) { + int ret2; + D("Error %d during bridge '%s' regops()", + ret, modified_bdg_name); + ret2 = netmap_bdg_destroy(modified_bdg_name, + conf->mod_bdg_auth_token); + if (ret2) { + /* cannot happen */ + D("Error %d during bridge '%s' destroy(), " + "this should never happen", + ret2, modified_bdg_name); + } + initialize_conf(conf); + --active_vlan_conf; + return ret; + } + vv_try_module_get(); + + nm_prinf("vale_vlan: successfully created " + "configuration '%s'\n", conf_name); + return 0; +} + + + +/* Fails if the conf doesn't exist + * + * must be called with GLOBAL_LOCK + */ +static int +vale_vlan_select_conf(const char *conf_name, uint16_t *conf_index) +{ + int i; + + for (i = 0; i < active_vlan_conf; ++i) { + int index = vlan_conf_index[i]; + if (strcmp(vlan_confs[index].conf_name, conf_name) == 0) { + *conf_index = index; + nm_prinf("vale_vlan: successfully selected " + "configuration '%s'\n", conf_name); + return 0; + } + } + + nm_prinf("vale_vlan: a configuration named '%s' doesn't exist\n", + conf_name); + return ENXIO; +} + + + +/* Fails if the conf doesn't exist or the modified bridge isn't empty + * + * must be called with GLOBAL_LOCK + */ +static int +vale_vlan_delete_conf(const char *conf_name) +{ + uint16_t conf_index = MAX_VLAN_CONFS; + char modified_bdg_name[IF_NAMESIZE]; + struct vale_vlan_conf *conf = NULL; + uint16_t i; + int ret; + + for (i = 0; i < active_vlan_conf; ++i) { + int index = vlan_conf_index[i]; + if (strcmp(vlan_confs[index].conf_name, conf_name) == 0) { + conf = &vlan_confs[index]; + conf_index = i; + break; + } + } + + if (!conf || i == active_vlan_conf) { + /* conf doesn't exist */ + return ENXIO; } + + /* redundant check */ for (i = 0; i < MAX_VLAN_ID; ++i) { - l_data->vlan_to_port[i] = NM_BDG_NOPORT; + if (conf->number_of_ports[i] != 0) { + D("conf->number_of_ports[%d] = %d", + i, conf->number_of_ports[i]); + return EBUSY; + } + } + + get_modified_bdg_name(modified_bdg_name, sizeof(modified_bdg_name), + conf_name); + ret = netmap_bdg_destroy(modified_bdg_name, + conf->mod_bdg_auth_token); + if (ret) { + /* cannot happen (?) */ + D("Error %d during bridge '%s' destroy(), SHOULD NOT HAPPEN", + ret, modified_bdg_name); + return ret; } + + conf->conf_name[0] = '\0'; /* marks conf slot as free */ + vlan_conf_index[conf_index] = vlan_conf_index[--active_vlan_conf]; + vv_module_put(); + return 0; +} + + +/* returns 0 if conf_index isn't a possible index or if + * the conf entry isn't in use + * + * must be called with GLOBAL_LOCK + */ +static int +does_conf_exist(int conf_index) +{ + + if (conf_index < 0 || conf_index >= MAX_VLAN_CONFS) { + return 0; + } + return vlan_confs[conf_index].conf_name[0] != '\0'; +} + + + +#define NM_API_VERSION 12 + + + +static void * +modify_trunk_port(void *private_data, void *callback_data, int *error) +{ + struct vlan_lookup_data *l_data = private_data; + uint32_t *new_trunk_port = callback_data; + + l_data->trunk_port = *new_trunk_port; + *error = 0; + return l_data; +} + + + +struct mod_access_port { + uint32_t old_port_index; + uint32_t new_port_index; + uint16_t old_vlan_id; + uint16_t new_vlan_id; +}; + + + +static void * +modify_access_port(void *private_data, void *callback_data, int *error) +{ + struct vlan_lookup_data *l_data = private_data; + struct mod_access_port *mod = callback_data; + + l_data->port_to_vlan[mod->old_port_index] = mod->new_vlan_id; + l_data->vlan_to_port[mod->old_vlan_id] = mod->new_port_index; + *error = 0; + return l_data; } @@ -227,7 +535,7 @@ D("Trying to create port '%s'", name); bzero(&hdr, sizeof(hdr)); - hdr.nr_version = NETMAP_API; + hdr.nr_version = NM_API_VERSION; hdr.nr_reqtype = NETMAP_REQ_VALE_NEWIF; strncpy(hdr.nr_name, name, sizeof(hdr.nr_name)); @@ -264,6 +572,54 @@ static int +attach_port_list(struct vale_vlan_conf *conf, const char *bdg_name, + const char *port_name, uint8_t port_type, uint16_t vlan_id) +{ + struct port_elem *p_elem = NULL; + + p_elem = vv_malloc(sizeof(struct port_elem)); + if (!p_elem) { + return EFAULT; + } + + vv_list_elem_init(p_elem, list); + p_elem->port_desc.vlan_id = vlan_id; + p_elem->port_desc.port_type = port_type; + snprintf(p_elem->port_desc.bdg_name, + sizeof(p_elem->port_desc.bdg_name), "%s", bdg_name); + snprintf(p_elem->port_desc.port_name, + sizeof(p_elem->port_desc.port_name), "%s", port_name); + vv_list_insert_head(&conf->port_list, p_elem, list); + return 0; +} + + + +static int +detach_port_list(struct vale_vlan_conf *conf, const char *port_name) +{ + struct port_elem *cursor = NULL; + struct port_elem *next = NULL; + + vv_list_foreach_safe(cursor, &conf->port_list, list, next) { + if (strcmp(cursor->port_desc.port_name, port_name) == 0) { + vv_list_remove(cursor, list); + vv_free(cursor); + return 0; + } + } + + return ENXIO; +} + + + +static int detach_trunk_port(struct vale_vlan_conf *, const char *, uint16_t); +static int detach_vlan_port(struct vale_vlan_conf *, const char *, uint16_t); + + + +static int attach_port(const char *bdg_name, const char *port_name, void *auth_token, uint32_t *port_index) { @@ -276,7 +632,7 @@ nmr_att.reg.nr_mode = NR_REG_ALL_NIC; bzero(&hdr, sizeof(hdr)); - hdr.nr_version = NETMAP_API; + hdr.nr_version = NM_API_VERSION; hdr.nr_reqtype = NETMAP_REQ_VALE_ATTACH; hdr.nr_body = (uint64_t)&nmr_att; snprintf(hdr.nr_name, sizeof(hdr.nr_name), "%s%s", bdg_name, port_name); @@ -286,9 +642,7 @@ vv_try_module_get(); } - if (port_index != NULL) { - *port_index = nmr_att.port_index; - } + *port_index = nmr_att.port_index; return ret; } @@ -306,7 +660,7 @@ bzero(&nmr_det, sizeof(nmr_det)); bzero(&hdr, sizeof(hdr)); - hdr.nr_version = NETMAP_API; + hdr.nr_version = NM_API_VERSION; hdr.nr_reqtype = NETMAP_REQ_VALE_DETACH; hdr.nr_body = (uint64_t)&nmr_det; snprintf(hdr.nr_name, sizeof(hdr.nr_name), "%s%s", bdg_name, port_name); @@ -315,214 +669,707 @@ if (ret == 0) { vv_module_put(); } - if (port_index != NULL) { - *port_index = nmr_det.port_index; + *port_index = nmr_det.port_index; + return ret; +} + + + +static int +attach_vlan_port(struct vale_vlan_conf *conf, const char *port_name, + uint16_t vlan_id) +{ + void *vlan_bdg_auth_token = conf->vlan_bdg_auth_tokens[vlan_id]; + uint32_t port_index = NM_BDG_NOPORT; + char modified_bdg_name[IF_NAMESIZE]; + char vlan_bdg_name[IF_NAMESIZE]; + struct mod_access_port mod_ap; + char ap_name[IF_NAMESIZE]; + int ret = 0; + + D("Trying to attach port '%s' with vlan id: %d to conf '%s'", + port_name, vlan_id, conf->conf_name); + if (vlan_id == 0x000 || vlan_id == 0xFFF) { + return EINVAL; + } + get_modified_bdg_name(modified_bdg_name, sizeof(modified_bdg_name), + conf->conf_name); + get_vlan_bdg_name(vlan_bdg_name, sizeof(vlan_bdg_name), conf->conf_name, + vlan_id); + + if (conf->number_of_ports[vlan_id] == 0) { + /* we need to create a bridge in exclusive mode */ + vlan_bdg_auth_token = netmap_bdg_create(vlan_bdg_name, &ret); + if (vlan_bdg_auth_token == NULL || ret != 0) { + return ret; + } + + conf->vlan_bdg_auth_tokens[vlan_id] = vlan_bdg_auth_token; + } + + ret = attach_port(vlan_bdg_name, port_name, vlan_bdg_auth_token, + &port_index); + if (ret) { + goto l_destroy_vlan_bdg; + } + + if (++conf->number_of_ports[vlan_id] != 1) { + /* an access port has alredy been created and attached to the + * modified bridge + */ + return ret; + } + + /* we need to create an access port and attach it + * to the modified bridge + */ + get_ap_name(ap_name, sizeof(ap_name), conf->conf_name, vlan_id); + ret = create_vale_port(ap_name); + if (ret) { + goto l_detach_vlan_port; + } + + ret = attach_port(vlan_bdg_name, ap_name, vlan_bdg_auth_token, + &port_index); + if (ret) { + goto l_destroy_access_port; + } + + ret = attach_port(modified_bdg_name, ap_name, + conf->mod_bdg_auth_token, &port_index); + if (ret) { + goto l_detach_access_port_vlan_bdg; + } + + /* this can fail only if bdg_name doesn't exist or hasn't been modified + * by us, and in either case we would have alredy failed one of our + * previous call + */ + mod_ap.old_port_index = mod_ap.new_port_index = port_index; + mod_ap.old_vlan_id = mod_ap.new_vlan_id = vlan_id; + nm_bdg_update_private_data(modified_bdg_name, modify_access_port, + &mod_ap, conf->mod_bdg_auth_token); + + return ret; + +l_detach_access_port_vlan_bdg: + /* cannot fail */ + detach_port(vlan_bdg_name, ap_name, vlan_bdg_auth_token, &port_index); + +l_destroy_access_port: + /* cannot fail */ + destroy_vale_port(ap_name); + +l_detach_vlan_port: + /* cannot fail */ + detach_port(vlan_bdg_name, port_name, vlan_bdg_auth_token, &port_index); + --conf->number_of_ports[vlan_id]; + +l_destroy_vlan_bdg: + if (conf->number_of_ports[vlan_id] == 0) { + /* we need to destroy the vlan bridge only when we fail + * something after creating it + */ + conf->vlan_bdg_auth_tokens[vlan_id] = NULL; + /* cannot fail */ + netmap_bdg_destroy(vlan_bdg_name, vlan_bdg_auth_token); + } + + return ret; +} + + + +static int +attach_trunk_port(struct vale_vlan_conf *conf, const char *port_name, + uint16_t vlan_id) +{ + uint32_t port_index = NM_BDG_NOPORT; + char mod_bdg_name[IF_NAMESIZE]; + int ret = 0; + + if (vlan_id != 0xFFF || conf->l_data.trunk_port != NM_BDG_NOPORT) { + return EINVAL; } + + get_modified_bdg_name(mod_bdg_name, sizeof(mod_bdg_name), + conf->conf_name); + ret = attach_port(mod_bdg_name, port_name, conf->mod_bdg_auth_token, + &port_index); + if (ret) { + return ret; + } + + /* this can't fail because we have the bridge in exclusive mode */ + nm_bdg_update_private_data(mod_bdg_name, modify_trunk_port, + &port_index, conf->mod_bdg_auth_token); return ret; } -#define VALE_V1A "valev1A:" -#define VALE_V1B "valev1B:" -#define VALE_V2A "valev2A:" -#define VALE_V2B "valev2B:" -#define VALE_V500B "valev500B:" -#define VALE_MODA "valemodA:" -#define VALE_MODB "valemodB:" -void *token_v1_A; -void *token_v1_B; -void *token_v2_A; -void *token_v2_B; -void *token_v500_B; -void *token_A; -void *token_B; -struct vlan_lookup_data data_A; -struct vlan_lookup_data data_B; +static int +action_attach(struct vale_vlan_conf *conf, const char *port_name, + uint8_t port_type, uint16_t vlan_id) +{ + char bdg_name[IF_NAMESIZE]; + int ret = 0; + switch (port_type){ + case TRUNK_PORT: + ret = attach_trunk_port(conf, port_name, vlan_id); + if (ret) { + return ret; + } + get_modified_bdg_name(bdg_name, sizeof(bdg_name), + conf->conf_name); + break; + case VLAN_PORT: + ret = attach_vlan_port(conf, port_name, vlan_id); + if (ret) { + return ret; + } + get_vlan_bdg_name(bdg_name, sizeof(bdg_name), conf->conf_name, + vlan_id); + break; -static void -create_ports(void) + default: + return EINVAL; + } + + + ret = attach_port_list(conf, bdg_name, port_name, port_type, vlan_id); + if (ret) { + switch (port_type){ + case TRUNK_PORT: + /* cannot fail */ + detach_trunk_port(conf, port_name, vlan_id); + break; + + case VLAN_PORT: + /* cannot fail */ + detach_vlan_port(conf, port_name, vlan_id); + break; + } + } + + return ret; +} + + + +static int +action_create_and_attach(struct vale_vlan_conf *conf, const char *port_name, + uint8_t port_type, uint16_t vlan_id) { + int ret = 0; + + ret = create_vale_port(port_name); + if (ret) { + return ret; + } + + ret = action_attach(conf, port_name, port_type, vlan_id); + if (ret) { + /* cannot fail */ + destroy_vale_port(port_name); + } - create_vale_port("v1"); - create_vale_port("v2"); - create_vale_port("v3"); - create_vale_port("v4"); - create_vale_port("v5"); - create_vale_port("v6"); - create_vale_port("vtp"); - create_vale_port("ap1A"); - create_vale_port("ap1B"); - create_vale_port("ap2A"); - create_vale_port("ap2B"); - create_vale_port("ap500B"); + return ret; } -static void -create_bridges(void) +static int +detach_trunk_port(struct vale_vlan_conf *conf, const char *port_name, + uint16_t vlan_id) { - int ret; + uint32_t port_index = NM_BDG_NOPORT; + char bdg_name[IF_NAMESIZE]; + int ret = 0; + + if (vlan_id != 0xFFF) { + return EINVAL; + } - token_A = netmap_bdg_create(VALE_MODA, &ret); - token_B = netmap_bdg_create(VALE_MODB, &ret); - token_v1_A = netmap_bdg_create(VALE_V1A, &ret); - token_v1_B = netmap_bdg_create(VALE_V1B, &ret); - token_v2_A = netmap_bdg_create(VALE_V2A, &ret); - token_v2_B = netmap_bdg_create(VALE_V2B, &ret); - token_v500_B = netmap_bdg_create(VALE_V500B, &ret); + get_modified_bdg_name(bdg_name, sizeof(bdg_name), conf->conf_name); + ret = detach_port(bdg_name, port_name, conf->mod_bdg_auth_token, + &port_index); + if (ret) { + return ret; + } + + port_index = NM_BDG_NOPORT; + /* this can't fail because we have the bridge in exlusive mode */ + nm_bdg_update_private_data(bdg_name, modify_trunk_port, + &port_index, conf->mod_bdg_auth_token); + return ret; } -static void -connect_ports(void) +static int +detach_vlan_port(struct vale_vlan_conf *conf, const char *port_name, + uint16_t vlan_id) { + struct mod_access_port mod_access_port; + uint32_t port_index = NM_BDG_NOPORT; + void *vlan_bdg_auth_token = NULL; + char modified_bdg_name[IF_NAMESIZE]; + char vlan_bdg_name[IF_NAMESIZE]; + char ap_name[IF_NAMESIZE]; + int ret = 0; + + if (vlan_id == 0x000 || vlan_id == 0xFFF) { + return EINVAL; + } + get_vlan_bdg_name(vlan_bdg_name, sizeof(vlan_bdg_name), conf->conf_name, + vlan_id); + get_modified_bdg_name(modified_bdg_name, sizeof(modified_bdg_name), + conf->conf_name); + get_ap_name(ap_name, sizeof(ap_name), conf->conf_name, vlan_id); + vlan_bdg_auth_token = conf->vlan_bdg_auth_tokens[vlan_id]; + + ret = detach_port(vlan_bdg_name, port_name, vlan_bdg_auth_token, + &port_index); + if (ret) { + return ret; + } + + if (--conf->number_of_ports[vlan_id] != 0) { + /* there are still other vlan port on this vlan bridge */ + return ret; + } + + /* we have just detached the last vlan port on this bridge, we need + * to remove (and destroy) the access port and the bridge as well + */ + ret = detach_port(modified_bdg_name, ap_name, + conf->mod_bdg_auth_token, &port_index); + if (ret) { + goto l_attach_vlan_port; + } + + ret = detach_port(vlan_bdg_name, ap_name, vlan_bdg_auth_token, + &port_index); + if (ret) { + goto l_attach_access_port_mod_bdg; + } + + ret = destroy_vale_port(ap_name); + if (ret) { + goto l_attach_access_port_vlan_bdg; + } + + ret = netmap_bdg_destroy(vlan_bdg_name, vlan_bdg_auth_token); + if (ret) { + /* cannot happen (?) */ + goto l_create_access_port; + } - attach_port(VALE_V1A, "v1", token_v1_A, NULL); - attach_port(VALE_V1A, "v2", token_v1_A, NULL); - attach_port(VALE_V1A, "ap1A", token_v1_A, NULL); + mod_access_port.old_port_index = port_index; + mod_access_port.new_port_index = NM_BDG_NOPORT; + mod_access_port.old_vlan_id = vlan_id; + mod_access_port.new_vlan_id = 0x000; + /* this can't fail because we have the bridge in exlusive mode */ + nm_bdg_update_private_data(modified_bdg_name, modify_access_port, + &mod_access_port, conf->mod_bdg_auth_token); - attach_port(VALE_V2A, "v3", token_v2_A, NULL); - attach_port(VALE_V2A, "v3", token_v2_A, NULL); - attach_port(VALE_V2A, "ap2A", token_v2_A, NULL); - attach_port(VALE_V1B, "v4", token_v1_B, NULL); - attach_port(VALE_V1B, "ap1B", token_v1_B, NULL); + return ret; - attach_port(VALE_V2B, "v5", token_v2_B, NULL); - attach_port(VALE_V2B, "ap2B", token_v2_B, NULL); +l_create_access_port: + create_vale_port(ap_name); /* cannot fail */ - attach_port(VALE_V500B, "v6", token_v500_B, NULL); - attach_port(VALE_V500B, "ap500B", token_v500_B, NULL); +l_attach_access_port_vlan_bdg: + /* cannot fail */ + attach_port(vlan_bdg_name, ap_name, vlan_bdg_auth_token, &port_index); + +l_attach_access_port_mod_bdg: + /* cannot fail */ + attach_port(modified_bdg_name, ap_name, conf->mod_bdg_auth_token, + &port_index); + +l_attach_vlan_port: + /* cannot fail */ + attach_port(vlan_bdg_name, port_name, vlan_bdg_auth_token, &port_index); + ++conf->number_of_ports[vlan_id]; - attach_port(VALE_MODA, "ap1A", token_A, NULL); - attach_port(VALE_MODA, "ap2A", token_A, NULL); - attach_port(VALE_MODA, "vtp", token_A, NULL); + return ret; - attach_port(VALE_MODB, "ap1B", token_B, NULL); - attach_port(VALE_MODB, "ap2B", token_B, NULL); - attach_port(VALE_MODB, "ap500B", token_B, NULL); - attach_port(VALE_MODB, "vtp", token_B, NULL); } -static void -delete_ports(void) +static int +search_vlan_id_of(struct vale_vlan_conf *conf, const char *port_name, + uint16_t *vlan_id) { + struct port_elem *p_elem = NULL; - destroy_vale_port("v1"); - destroy_vale_port("v2"); - destroy_vale_port("v3"); - destroy_vale_port("v4"); - destroy_vale_port("v5"); - destroy_vale_port("v6"); - destroy_vale_port("vtp"); - destroy_vale_port("ap1A"); - destroy_vale_port("ap1B"); - destroy_vale_port("ap2A"); - destroy_vale_port("ap2B"); - destroy_vale_port("ap500B"); + vv_list_foreach(p_elem, &conf->port_list, list) { + if (strcmp(p_elem->port_desc.port_name, port_name) == 0) { + *vlan_id = p_elem->port_desc.vlan_id; + return 0; + } + } + return ENXIO; } -static void -delete_bridges(void) +static int +search_trunk_port_of(struct vale_vlan_conf *conf, char *trunk_port_name) { + struct port_elem *p_elem = NULL; - netmap_bdg_destroy(VALE_MODA, &token_A); - netmap_bdg_destroy(VALE_MODB, &token_B); - netmap_bdg_destroy(VALE_V1A, &token_v1_A); - netmap_bdg_destroy(VALE_V1B, &token_v1_B); - netmap_bdg_destroy(VALE_V2A, &token_v2_A); - netmap_bdg_destroy(VALE_V2B, &token_v2_B); - netmap_bdg_destroy(VALE_V500B, &token_v500_B); + vv_list_foreach(p_elem, &conf->port_list, list) { + if (p_elem->port_desc.port_type == TRUNK_PORT) { + snprintf(trunk_port_name, IF_NAMESIZE, "%s", + p_elem->port_desc.port_name); + return 0; + } + } + return ENXIO; } -static void -detach_ports(void) +static int +action_detach(struct vale_vlan_conf *conf, char *port_name, uint8_t port_type, + uint16_t vlan_id) { + int ret = 0; + + switch (port_type) { + case TRUNK_PORT: + if (port_name[0] == '\0') { + ret = search_trunk_port_of(conf, port_name); + if (ret) { + return ret; + } + } + ret = detach_trunk_port(conf, port_name, vlan_id); + if (ret) { + return ret; + } + break; + case VLAN_PORT: + if (vlan_id == 0xFFF) { + ret = search_vlan_id_of(conf, port_name, &vlan_id); + if (ret) { + return ret; + } + } - detach_port(VALE_MODB, "vtp", token_B, NULL); - detach_port(VALE_MODB, "ap500B", token_B, NULL); - detach_port(VALE_MODB, "ap2B", token_B, NULL); - detach_port(VALE_MODB, "ap1B", token_B, NULL); + ret = detach_vlan_port(conf, port_name, vlan_id); + if (ret) { + return ret; + } + break; + default: + return EINVAL; + } - detach_port(VALE_MODA, "vtp", token_A, NULL); - detach_port(VALE_MODA, "ap2A", token_A, NULL); - detach_port(VALE_MODA, "ap1A", token_A, NULL); + ret = detach_port_list(conf, port_name); + if (ret) { + switch (port_type){ + case TRUNK_PORT: + ret = attach_trunk_port(conf, port_name, vlan_id); + break; + + case VLAN_PORT: + ret = attach_vlan_port(conf, port_name, vlan_id); + break; + } + } + return ret; +} - detach_port(VALE_V500B, "ap500B", token_v500_B, NULL); - detach_port(VALE_V500B, "v6", token_v500_B, NULL); - detach_port(VALE_V2B, "ap2B", token_v2_B, NULL); - detach_port(VALE_V2B, "v5", token_v2_B, NULL); - detach_port(VALE_V1B, "ap1B", token_v1_B, NULL); - detach_port(VALE_V1B, "v4", token_v1_B, NULL); +static int +action_detach_and_destroy(struct vale_vlan_conf *conf, char *port_name, + uint8_t port_type, uint16_t vlan_id) +{ + int ret = 0; - detach_port(VALE_V2A, "ap2A", token_v2_A, NULL); - detach_port(VALE_V2A, "v3", token_v2_A, NULL); - detach_port(VALE_V2A, "v3", token_v2_A, NULL); + ret = action_detach(conf, port_name, port_type, vlan_id); + if (ret) { + return ret; + } - detach_port(VALE_V1A, "ap1A", token_v1_A, NULL); - detach_port(VALE_V1A, "v2", token_v1_A, NULL); - detach_port(VALE_V1A, "v1", token_v1_A, NULL); + ret = destroy_vale_port(port_name); + if (ret) { + /* cannot fail */ + action_attach(conf, port_name, port_type, vlan_id); + } + return ret; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805282005.w4SK5qVE018660>