Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

device: add support for configuring vrf #38

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ SET(SOURCES
iprule.c proto.c proto-static.c proto-shell.c
config.c device.c bridge.c veth.c vlan.c alias.c
macvlan.c ubus.c vlandev.c wireless.c
extdev.c bonding.c)
extdev.c bonding.c vrf.c)


FIND_LIBRARY(uci NAMES uci)
Expand Down
11 changes: 11 additions & 0 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "wireless.h"
#include "config.h"
#include "ubus.h"
#include "system.h"

bool config_init = false;

Expand Down Expand Up @@ -537,6 +538,16 @@ config_init_globals(void)
const char *ula_prefix = uci_lookup_option_string(
uci_ctx, globals, "ula_prefix");
interface_ip_set_ula_prefix(ula_prefix);

const char *tcp_l3mdev = uci_lookup_option_string(
uci_ctx, globals, "tcp_l3mdev");
if (tcp_l3mdev)
system_tcp_l3mdev(!strcmp(tcp_l3mdev, "1"));

const char *udp_l3mdev = uci_lookup_option_string(
uci_ctx, globals, "udp_l3mdev");
if (udp_l3mdev)
system_udp_l3mdev(!strcmp(udp_l3mdev, "1"));
}

static void
Expand Down
109 changes: 109 additions & 0 deletions system-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,115 @@ int system_bridge_vlan(const char *iface, uint16_t vid, int16_t vid_end, bool ad
return ret;
}

int system_vrf_addvrf(struct device *vrf, unsigned int table)
{
struct nlattr *linkinfo, *data;
struct nl_msg *msg;
int rv;

msg = system_ifinfo_msg(vrf->ifname, RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
if (!msg)
return -1;

if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
goto nla_put_failure;

nla_put_string(msg, IFLA_INFO_KIND, "vrf");

if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
goto nla_put_failure;

nla_put_u32(msg, IFLA_VRF_TABLE, table);

nla_nest_end(msg, data);
nla_nest_end(msg, linkinfo);

rv = system_rtnl_call(msg);
if (rv)
D(SYSTEM, "Error adding vrf '%s': %d\n", vrf->ifname, rv);

return rv;

nla_put_failure:
nlmsg_free(msg);
return -ENOMEM;
}

int system_vrf_delvrf(struct device *vrf)
{
return system_link_del(vrf->ifname);
}

static char *system_get_vrf(const char *name, char *buf, int buflen)
{
char master[PATH_MAX];
char *path;
ssize_t len = -1;

if (snprintf(master, sizeof(master), "%s/devices/virtual/net/%s/master", sysfs_path, name) <= 0)
return NULL;

len = readlink(master, buf, buflen);
if (len < 0)
return NULL;

buf[len] = 0;
path = strrchr(buf, '/');
if (!path)
return NULL;

return path + 1;
}

static int
system_vrf_if(int vrf_index, struct device *dev)
{
struct nl_msg *msg;

msg = __system_ifinfo_msg(AF_UNSPEC, dev->ifindex, NULL, RTM_SETLINK, NLM_F_REQUEST);
if (!msg)
return -1;

nla_put_u32(msg, IFLA_MASTER, vrf_index);
return system_rtnl_call(msg);
}

int system_vrf_addif(struct device *vrf, struct device *dev)
{
char *oldvrf;
int tries = 0;
int ret;

retry:
ret = 0;
oldvrf = system_get_vrf(dev->ifname, dev_buf, sizeof(dev_buf));
if (!oldvrf || strcmp(oldvrf, vrf->ifname) != 0) {
ret = system_vrf_if(vrf->ifindex, dev);
tries++;
D(SYSTEM, "Failed to add device '%s' to vrf '%s' (tries=%d): %s\n",
dev->ifname, vrf->ifname, tries, strerror(errno));
if (tries <= 3)
goto retry;
}

return ret;
}

int system_vrf_delif(struct device *vrf, struct device *dev)
{
return system_vrf_if(0, dev);
}

void system_tcp_l3mdev(bool enable)
{
system_set_dev_sysctl("ipv4", "tcp_l3mdev_accept", ".", enable ? "1" : "0");
}

void system_udp_l3mdev(bool enable)
{
system_set_dev_sysctl("ipv4", "udp_l3mdev_accept", ".", enable ? "1" : "0");
}

int system_bonding_set_device(struct device *dev, struct bonding_config *cfg)
{
const char *ifname = dev->ifname;
Expand Down
8 changes: 8 additions & 0 deletions system.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ int system_bridge_vlan(const char *iface, uint16_t vid, int16_t vid_end, bool ad
int system_bridge_vlan_check(struct device *dev, char *ifname);
void system_bridge_set_stp_state(struct device *dev, bool val);

int system_vrf_addvrf(struct device *vrf, unsigned int table);
int system_vrf_delvrf(struct device *vrf);
int system_vrf_addif(struct device *vrf, struct device *dev);
int system_vrf_delif(struct device *vrf, struct device *dev);

void system_tcp_l3mdev(bool enable);
void system_udp_l3mdev(bool enable);

int system_bonding_set_device(struct device *dev, struct bonding_config *cfg);
int system_bonding_set_port(struct device *dev, struct device *port, bool add, bool primary);

Expand Down
Loading