Skip to content

Commit

Permalink
[Bridge + 8021q] Remove virtual interfaces on vlan_del
Browse files Browse the repository at this point in the history
* when a VLAN is removed all the virtual interfaces created
for this VLAN in trunk interfaces must be removed.

Signed-off-by: Claudiu Ghioc <claudiu.ghioc@gmail.com>
  • Loading branch information
claudiughioc committed May 15, 2013
1 parent 86d8498 commit 2bb6c87
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 16 deletions.
84 changes: 70 additions & 14 deletions userspace/switch/linux/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ static int __manage_vif(struct linux_context *lnx_ctx, char *if_name,

/* Create a new interface in a given VLAN */
strcpy(if_request.device1, if_name);
if_request.u.VID = vlan_id;
if (ADD_VLAN_CMD == cmd)
if_request.u.VID = vlan_id;
if_request.cmd = cmd;

VLAN_SOCK_OPEN(lnx_ctx, vlan_sfd);
Expand Down Expand Up @@ -126,8 +127,8 @@ static int linux_init(struct switch_operations *sw_ops)
static int if_add(struct switch_operations *sw_ops, int ifindex, int mode)
{
struct if_data data;
struct net_switch_device device;
int ret, if_sfd;
struct net_switch_device device, vif_device;
int ret = 0, if_sfd;
char if_name[IFNAMSIZE], vif_name[IFNAMSIZE];
unsigned char vlan_bitmap[512];
struct linux_context *lnx_ctx = SWLINUX_CTX(sw_ops);
Expand All @@ -148,7 +149,7 @@ static int if_add(struct switch_operations *sw_ops, int ifindex, int mode)
goto create_data;
}

/* Create interfaces for each VLAN in the switch */
/* Trunk: create interfaces for each VLAN in the switch */
mm_lock(mm);

mm_list_for_each(mm, ptr, mm_ptr(mm, &SHM->vlan_data)) {
Expand All @@ -157,10 +158,19 @@ static int if_add(struct switch_operations *sw_ops, int ifindex, int mode)

/* Use 8021q to add a new interface */
ret = __add_vif(lnx_ctx, if_name, v_data->vlan_id);
if (ret) {
mm_unlock(mm);
goto out;
}
if (ret)
continue;

/* Add virtual interface information to VLAN data */
sprintf(vif_name, "%s.%d", if_name, v_data->vlan_id);
strcpy(vif_device.name, vif_name);
vif_device.vlan = v_data->vlan_id;

IF_SOCK_OPEN(lnx_ctx, if_sfd);
vif_device.ifindex = if_get_index(vif_name, if_sfd);
IF_SOCK_CLOSE(lnx_ctx, if_sfd);

add_vif_data(v_data->vlan_id, vif_device);
}

mm_unlock(mm);
Expand All @@ -177,16 +187,16 @@ static int if_add(struct switch_operations *sw_ops, int ifindex, int mode)
data.mode = mode;
set_if_data(ifindex, data);

out:
return ret;
}

static int if_remove(struct switch_operations *sw_ops, int ifindex)
{
int ret = 0, if_sfd;
struct linux_context *lnx_ctx = SWLINUX_CTX(sw_ops);
char if_name[IFNAMSIZE];
char if_name[IFNAMSIZE], vif_name[IFNAMSIZE];
struct if_data data;
mm_ptr_t ptr;

/* Get the name of the interface */
IF_SOCK_OPEN(lnx_ctx, if_sfd);
Expand All @@ -202,7 +212,24 @@ static int if_remove(struct switch_operations *sw_ops, int ifindex)
goto remove_data;
}

/* TODO Remove all the virtual interfaces for TRUNK mode */
/* Remove all the virtual interfaces for TRUNK mode */
mm_lock(mm);

mm_list_for_each(mm, ptr, mm_ptr(mm, &SHM->vlan_data)) {
struct vlan_data *v_data =
mm_addr(mm, mm_list_entry(ptr, struct vlan_data, lh));

/* Use 8021q to remove the virtual interface */
sprintf(vif_name, "%s.%d", if_name, v_data->vlan_id);
ret = __remove_vif(lnx_ctx, vif_name);
if (ret)
continue;

/* Remove virtual interface information from VLAN data */
del_vif_data(v_data->vlan_id, if_name);
}

mm_unlock(mm);

remove_data:
/* Remove the interface specific data */
Expand Down Expand Up @@ -237,7 +264,6 @@ static int vlan_add(struct switch_operations *sw_ops, int vlan)
if (IF_MODE_ACCESS == if_data->mode)
continue;


/* Create a new virtual interface */
ret = __add_vif(lnx_ctx, if_data->device.name, vlan);
if (ret)
Expand All @@ -261,12 +287,42 @@ static int vlan_add(struct switch_operations *sw_ops, int vlan)

static int vlan_del(struct switch_operations *sw_ops, int vlan)
{
int ret;
int ret = 0;
struct linux_context *lnx_ctx = SWLINUX_CTX(sw_ops);
struct vlan_data *v_data;
mm_ptr_t ptr, tmp;

ret = remove_bridge(lnx_ctx, vlan);
if (ret)
return ret;

/* Get VLAN data */
ret = get_vlan_data(vlan, &v_data);
if (ret)
return ret;


/* Remove the virtual interfaces for all the trunk interfaces */
mm_lock(mm);

mm_list_for_each_safe(mm, ptr, tmp, mm_ptr(mm, &v_data->vif_list)) {
struct if_data *vif_data =
mm_addr(mm, mm_list_entry(ptr, struct if_data, lh));

ret = __remove_vif(lnx_ctx, vif_data->device.name);
if (ret)
continue;

mm_list_del(mm, ptr);
mm_free(mm, mm_list_entry(ptr, struct if_data, lh));
}

mm_unlock(mm);


/* Remove VLAN specific data */
ret = del_vlan_data(vlan);

/* TODO Remove VLAN specific data */
return ret;
}

Expand Down
32 changes: 30 additions & 2 deletions userspace/switch/switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -538,8 +538,6 @@ int add_vlan_data(int vlan_id)
{
mm_ptr_t lh, mm_v_data;
struct vlan_data *data;
mm_ptr_t mm_vif_data;
struct if_data *vif_data;
int ret = 0;

mm_lock(mm);
Expand Down Expand Up @@ -703,6 +701,36 @@ int add_vif_data(int vlan_id, struct net_switch_device device)
return ret;
}

void del_vif_data(int vlan_id, char *if_name)
{
int res = 0;
char vif_name[IFNAMSIZE];
struct vlan_data *v_data;
mm_ptr_t ret;

/* Get VLAN data */
res = get_vlan_data(vlan_id, &v_data);
if (res)
return;
sprintf(vif_name, "%s.%d", if_name, vlan_id);


/* Remove virtual interface information from VLAN data */
mm_lock(mm);

mm_list_for_each(mm, ret, mm_ptr(mm, &v_data->vif_list)) {
struct if_data *vif_data =
mm_addr(mm, mm_list_entry(ret, struct if_data, lh));
if (!strcmp(vif_data->device.name, vif_name))
break;
}
mm_list_del(mm, ret);
mm_free(mm, mm_list_entry(ret, struct if_data, lh));

mm_unlock(mm);

}

int switch_set_if_desc(int if_index, char *desc)
{
mm_ptr_t lh, mm_s_desc;
Expand Down
4 changes: 4 additions & 0 deletions userspace/switch/switch.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ int del_if_data(int if_index);
/* Add virtual interface specific information to VLAN data */
int add_vif_data(int vlan_id, struct net_switch_device device);

/* Remove virtual interface information from VLAN data */
void del_vif_data(int vlan_id, char *if_name);



/* Sets the cdp global configuration */
void switch_set_cdp(struct cdp_configuration *cdp);
Expand Down

0 comments on commit 2bb6c87

Please sign in to comment.