Skip to content

Commit

Permalink
[Bridge + 8021q] if_add: create a new interface for each VLAN
Browse files Browse the repository at this point in the history
* if_add: if the new interface must be in "trunk" mode, we create
a new virtual interface for each VLAN in the switch;

Signed-off-by: Claudiu Ghioc <claudiu.ghioc@gmail.com>
  • Loading branch information
claudiughioc committed May 14, 2013
1 parent 7896bb9 commit d8bf4d3
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 28 deletions.
122 changes: 96 additions & 26 deletions userspace/switch/linux/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,14 @@ static int remove_bridge(struct linux_context *lnx_ctx, int vlan_id)

static int add_bridge_if(struct linux_context *lnx_ctx, int vlan_id, int ifindex)
{
int ret = 0, if_sfd, bridge_sfd;
int ret = 0, bridge_sfd;
struct ifreq ifr;
char if_name[IFNAMSIZE], br_name[VLAN_NAME_LEN];
char br_name[VLAN_NAME_LEN];
unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 };

/* Get the name of the interface */
IF_SOCK_OPEN(lnx_ctx, if_sfd);
if_get_name(ifindex, if_sfd, if_name);
IF_SOCK_CLOSE(lnx_ctx, if_sfd);

/* Build the name of the bridge */
sprintf(br_name, "vlan%d", vlan_id);


/* Add the interface to the bridge */
strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
ifr.ifr_data = (char *) args;
Expand All @@ -77,15 +71,10 @@ static int add_bridge_if(struct linux_context *lnx_ctx, int vlan_id, int ifindex

static int remove_bridge_if(struct linux_context *lnx_ctx, int vlan_id, int ifindex)
{
int ret = 0, if_sfd, bridge_sfd;
int ret = 0, bridge_sfd;
struct ifreq ifr;
unsigned long args[4] = { BRCTL_DEL_IF, ifindex, 0, 0 };
char if_name[IFNAMSIZE], br_name[VLAN_NAME_LEN];

/* Get the name of the interface */
IF_SOCK_OPEN(lnx_ctx, if_sfd);
if_get_name(ifindex, if_sfd, if_name);
IF_SOCK_CLOSE(lnx_ctx, if_sfd);
char br_name[VLAN_NAME_LEN];

/* Build the name of the bridge */
sprintf(br_name, "vlan%d", vlan_id);
Expand All @@ -101,6 +90,34 @@ static int remove_bridge_if(struct linux_context *lnx_ctx, int vlan_id, int ifin
return ret;
}

static int __manage_vif(struct linux_context *lnx_ctx, char *if_name,
int vlan_id, int cmd)
{
int ret = 0, vlan_sfd;
struct vlan_ioctl_args if_request;

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

VLAN_SOCK_OPEN(lnx_ctx, vlan_sfd);
ret = ioctl(vlan_sfd, SIOCSIFVLAN, &if_request);
VLAN_SOCK_CLOSE(lnx_ctx, vlan_sfd);

return ret;
}

static int __add_vif(struct linux_context *lnx_ctx, char *if_name, int vlan_id)
{
return __manage_vif(lnx_ctx, if_name, vlan_id, ADD_VLAN_CMD);
}

static int __remove_vif(struct linux_context *lnx_ctx, char *if_name)
{
return __manage_vif(lnx_ctx, if_name, 0, DEL_VLAN_CMD);
}

static int linux_init(struct switch_operations *sw_ops)
{
return 0;
Expand All @@ -111,9 +128,10 @@ 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;
char if_name[IFNAMSIZE];
char if_name[IFNAMSIZE], vif_name[IFNAMSIZE];
unsigned char vlan_bitmap[512];
struct linux_context *lnx_ctx = SWLINUX_CTX(sw_ops);
mm_ptr_t ptr;


/* Get the name of the interface */
Expand All @@ -123,11 +141,31 @@ static int if_add(struct switch_operations *sw_ops, int ifindex, int mode)


/* Add the new interface to the default bridge */
ret = add_bridge_if(lnx_ctx, LINUX_DEFAULT_VLAN, ifindex);
if (ret)
return ret;


if (IF_MODE_ACCESS == mode) {
ret = add_bridge_if(lnx_ctx, LINUX_DEFAULT_VLAN, ifindex);
if (ret)
return ret;
goto create_data;
}

/* Create interfaces for each VLAN in the switch */
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 add a new interface */
ret = __add_vif(lnx_ctx, if_name, v_data->vlan_id);
if (ret) {
mm_unlock(mm);
goto out;
}
}

mm_unlock(mm);

create_data:
/* Create interface specific data */
strncpy(device.name, if_name, IFNAMSIZ);
device.ifindex = ifindex;
Expand All @@ -139,20 +177,36 @@ 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;
int ret = 0, if_sfd;
struct linux_context *lnx_ctx = SWLINUX_CTX(sw_ops);
char if_name[IFNAMSIZE];
struct if_data data;

/* Remove the new interface from the default bridge */
ret = remove_bridge_if(lnx_ctx, LINUX_DEFAULT_VLAN, ifindex);
/* Get the name of the interface */
IF_SOCK_OPEN(lnx_ctx, if_sfd);
if_get_name(ifindex, if_sfd, if_name);
IF_SOCK_CLOSE(lnx_ctx, if_sfd);

/* Get interface data */
get_if_data(ifindex, &data);

/* Remove the new interface from the default bridge for ACCES mode */
if (IF_MODE_ACCESS == data.mode) {
ret = remove_bridge_if(lnx_ctx, LINUX_DEFAULT_VLAN, ifindex);
goto remove_data;
}

/* TODO Remove all the virtual interfaces for TRUNK mode */

remove_data:
/* Remove the interface specific data */
del_if_data(ifindex);

return ret;
}

Expand All @@ -166,7 +220,23 @@ static int vlan_add(struct switch_operations *sw_ops, int vlan)
if (ret)
return ret;

/* TODO Create VLAN specific data */
/* Add new virtual interfaces for all the trunk interfaces */
LIST_HEAD(net_devices);

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

if (IF_MODE_ACCESS == if_data->mode)
continue;


}
mm_unlock(mm);

/* Create VLAN specific data */
set_vlan_data(vlan, net_devices);

return ret;
}
Expand Down
3 changes: 1 addition & 2 deletions userspace/switch/switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@
#include "linux.h"
#endif

static struct mm_private *mm = NULL;
#define SHM ((struct switch_mem *)MM_STATIC(mm))
struct mm_private *mm = NULL;
struct switch_operations *sw_ops;

static mm_ptr_t __switch_get_if_tag(int if_index)
Expand Down
2 changes: 2 additions & 0 deletions userspace/switch/switch.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
#define SW_MAX_PORT_DESC 31

extern struct switch_operations *sw_ops;
extern struct mm_private *mm;
#define SHM ((struct switch_mem *)MM_STATIC(mm))

/*
* Switch shared memory structure
Expand Down

0 comments on commit d8bf4d3

Please sign in to comment.