device: bridge: implement initial bridge setup
This commit is contained in:
parent
8b5af11ebe
commit
8d15854eb5
1 changed files with 118 additions and 4 deletions
|
@ -1,14 +1,128 @@
|
||||||
#include "device.h"
|
#include "device-common.h"
|
||||||
|
#include "netlink.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
static device_type_t device_type_bridge;
|
||||||
|
|
||||||
|
typedef struct _device_bridge {
|
||||||
|
device_t device;
|
||||||
|
device_common_t common;
|
||||||
|
} device_bridge_t;
|
||||||
|
|
||||||
|
static void bridge_free(device_t *dev) {
|
||||||
|
device_bridge_t *iface = container_of(dev, device_bridge_t, device);
|
||||||
|
|
||||||
|
VECTOR_FREE(iface->common.addrs);
|
||||||
|
free(NODE_NAME(dev));
|
||||||
|
free(iface);
|
||||||
|
}
|
||||||
|
|
||||||
static device_t * bridge_process_config(const char *name, struct json_object *config) {
|
static device_t * bridge_process_config(const char *name, struct json_object *config) {
|
||||||
printf("Bridge: %s\n", name);
|
device_bridge_t *iface = calloc(1, sizeof(*iface));
|
||||||
|
if (!iface)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
device_t *dev = &iface->device;
|
||||||
|
dev->type = &device_type_bridge;
|
||||||
|
|
||||||
|
NODE_NAME(dev) = strdup(name);
|
||||||
|
if (!NODE_NAME(dev)) {
|
||||||
|
free(iface);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
device_type_t device_type_bridge = {
|
if (!device_common_process_config(&iface->common, config))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return dev;
|
||||||
|
|
||||||
|
err:
|
||||||
|
bridge_free(dev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool bridge_nl_create(device_bridge_t *bridge) {
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
struct mnl_socket *nl = nl_socket();
|
||||||
|
|
||||||
|
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = RTM_NEWLINK;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE;
|
||||||
|
int seq = nlh->nlmsg_seq = nl_seq();
|
||||||
|
|
||||||
|
struct ifinfomsg *ifi = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifi));
|
||||||
|
ifi->ifi_family = AF_UNSPEC;
|
||||||
|
|
||||||
|
mnl_attr_put_str(nlh, IFLA_IFNAME, NODE_NAME(&bridge->device));
|
||||||
|
|
||||||
|
struct nlattr *linkinfo = mnl_attr_nest_start(nlh, IFLA_LINKINFO);
|
||||||
|
mnl_attr_put_str(nlh, IFLA_INFO_KIND, "bridge");
|
||||||
|
mnl_attr_nest_end(nlh, linkinfo);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, mnl_socket_get_portid(nl), NULL, NULL);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_cb_run");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bridge_init(device_t *dev) {
|
||||||
|
device_bridge_t *bridge = container_of(dev, device_bridge_t, device);
|
||||||
|
|
||||||
|
if (!bridge_nl_create(bridge))
|
||||||
|
return;
|
||||||
|
|
||||||
|
unsigned ifindex = if_nametoindex(NODE_NAME(dev));
|
||||||
|
if (!ifindex)
|
||||||
|
return;
|
||||||
|
|
||||||
|
device_common_init(&bridge->common, ifindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bridge_update(device_t *dev) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bridge_release(device_t *dev) {
|
||||||
|
/*
|
||||||
|
device_bridge_t *bridge = container_of(dev, device_bridge_t, device);
|
||||||
|
|
||||||
|
unsigned ifindex = if_nametoindex(NODE_NAME(dev));
|
||||||
|
if (!ifindex)
|
||||||
|
return;
|
||||||
|
|
||||||
|
device_common_release(&bridge->common, ifindex);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static device_type_t device_type_bridge = {
|
||||||
.process_config = bridge_process_config,
|
.process_config = bridge_process_config,
|
||||||
|
.free = bridge_free,
|
||||||
|
|
||||||
|
.init = bridge_init,
|
||||||
|
.update = bridge_update,
|
||||||
|
.release = bridge_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
|
|
Reference in a new issue