socsvn commit: r337258 - in soc2018/sduo/head/sys: dev/vale_vlan modules/vale_vlan net
sduo at FreeBSD.org
sduo at FreeBSD.org
Mon May 28 20:05:55 UTC 2018
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 ***
More information about the svn-soc-all
mailing list