mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 09:13:01 +02:00
statd: remove nl code and improve speed
This is a major redesign of statd interface handling. The goal here is to reduce the time it takes for statd to produce operational data for all interfaces on larger iron. Which manifested itself most notably in the CLI command "show interfaces". This patch removes the netlink interface subscriptions done by the statd c code. Instead statd now subscribes to the ietf-interfaces base path which means it will be invoked for all interfaces. If the user (sysrepo) has specified an explicit interface name such as eth0, it will be extracted by statd and passed down to Yanger. This patch also modifies Yanger to fit this new modus. No explicitly passed interface name now means all interfaces. Side note: The main culprit of the slow operational interface data is the time it takes to bootstrap python. Which prior to this patch was done for each interface. On the HW system I'm testing this patch on, runtime is reduced by a factor of 10. Signed-off-by: Richard Alpe <richard@bit42.se>
This commit is contained in:
committed by
Joachim Wiberg
parent
3e2b9fbd5e
commit
14128047e1
@@ -837,6 +837,26 @@ def add_vlans_to_bridge(brname, iface_out, mc_status):
|
||||
|
||||
insert(iface_out, "infix-interfaces:bridge", "vlans", "vlan", vlans)
|
||||
|
||||
def get_iface_data(ifname):
|
||||
iface_out = {}
|
||||
|
||||
add_ip_link(ifname, iface_out)
|
||||
add_ip_addr(ifname, iface_out)
|
||||
|
||||
if 'type' in iface_out and iface_out['type'] == "infix-if-type:ethernet":
|
||||
add_ethtool_groups(ifname, iface_out)
|
||||
add_ethtool_std(ifname, iface_out)
|
||||
|
||||
if 'type' in iface_out and iface_out['type'] == "infix-if-type:bridge":
|
||||
# Fail silent, multicast snooping may not be enabled on bridge
|
||||
mc_status = run_json_cmd(['mctl', '-p', 'show', 'igmp', 'json'],
|
||||
"igmp-status.json", default={},
|
||||
check=False)
|
||||
|
||||
add_vlans_to_bridge(ifname, iface_out, mc_status)
|
||||
add_mdb_to_bridge(ifname, iface_out, mc_status)
|
||||
|
||||
return iface_out
|
||||
|
||||
def main():
|
||||
global TESTPATH
|
||||
@@ -867,38 +887,20 @@ def main():
|
||||
logger.addHandler(log)
|
||||
|
||||
if args.model == 'ietf-interfaces':
|
||||
# For now, we handle each interface separately, as this is how it's
|
||||
# currently implemented in sysrepo. I.e sysrepo will subscribe to
|
||||
# each individual interface and query it for YANG data.
|
||||
|
||||
if not args.param:
|
||||
print("usage: yanger ietf-interfaces -p INTERFACE", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
yang_data = {
|
||||
"ietf-interfaces:interfaces": {
|
||||
"interface": [{}]
|
||||
"interface": []
|
||||
}
|
||||
}
|
||||
|
||||
ifname = args.param
|
||||
iface_out = yang_data['ietf-interfaces:interfaces']['interface'][0]
|
||||
|
||||
add_ip_link(ifname, iface_out)
|
||||
add_ip_addr(ifname, iface_out)
|
||||
|
||||
if 'type' in iface_out and iface_out['type'] == "infix-if-type:ethernet":
|
||||
add_ethtool_groups(ifname, iface_out)
|
||||
add_ethtool_std(ifname, iface_out)
|
||||
|
||||
if 'type' in iface_out and iface_out['type'] == "infix-if-type:bridge":
|
||||
# Fail silent, multicast snooping may not be enabled on bridge
|
||||
mc_status = run_json_cmd(['mctl', '-p', 'show', 'igmp', 'json'],
|
||||
"igmp-status.json", default={},
|
||||
check=False)
|
||||
|
||||
add_vlans_to_bridge(ifname, iface_out, mc_status)
|
||||
add_mdb_to_bridge(ifname, iface_out, mc_status)
|
||||
if args.param:
|
||||
iface_data = get_iface_data(args.param)
|
||||
yang_data['ietf-interfaces:interfaces']['interface'].append(iface_data)
|
||||
else:
|
||||
ifnames = os.listdir('/sys/class/net/')
|
||||
for ifname in ifnames:
|
||||
iface_data = get_iface_data(ifname)
|
||||
yang_data['ietf-interfaces:interfaces']['interface'].append(iface_data)
|
||||
|
||||
elif args.model == 'ietf-routing':
|
||||
yang_data = {
|
||||
|
||||
+96
-322
@@ -31,9 +31,6 @@
|
||||
#define MFD_NOEXEC_SEAL 0x0008U
|
||||
#endif
|
||||
|
||||
#define SOCK_RMEM_SIZE 1000000 /* Arbitrary chosen, default = 212992 */
|
||||
#define NL_BUF_SIZE 4096 /* Arbitrary chosen */
|
||||
|
||||
#define XPATH_MAX PATH_MAX
|
||||
#define XPATH_IFACE_BASE "/ietf-interfaces:interfaces"
|
||||
#define XPATH_ROUTING_BASE "/ietf-routing:routing/control-plane-protocols/control-plane-protocol"
|
||||
@@ -44,11 +41,7 @@
|
||||
|
||||
TAILQ_HEAD(sub_head, sub);
|
||||
|
||||
/* This should, with some modifications, be able to hold other subscription
|
||||
* types, not only interfaces.
|
||||
*/
|
||||
struct sub {
|
||||
char name[IFNAMSIZ + 3];
|
||||
struct ev_io watcher;
|
||||
sr_subscription_ctx_t *sr_sub;
|
||||
|
||||
@@ -56,80 +49,12 @@ struct sub {
|
||||
entries;
|
||||
};
|
||||
|
||||
struct netlink {
|
||||
int sd;
|
||||
struct ev_io watcher;
|
||||
};
|
||||
|
||||
struct statd {
|
||||
struct netlink nl;
|
||||
struct ev_loop *ev_loop;
|
||||
struct sub_head subs;
|
||||
sr_session_ctx_t *sr_ses;
|
||||
struct ev_loop *ev_loop;
|
||||
};
|
||||
|
||||
static void set_sock_rcvbuf(int sd, int size)
|
||||
{
|
||||
if (setsockopt(sd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) {
|
||||
perror("setsockopt");
|
||||
return;
|
||||
}
|
||||
DEBUG("Socket receive buffer size increased to: %d bytes", size);
|
||||
}
|
||||
|
||||
static int nl_sock_init(void)
|
||||
{
|
||||
struct sockaddr_nl addr;
|
||||
int sock;
|
||||
|
||||
sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (sock < 0) {
|
||||
ERROR("Error, creating netlink socket: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_groups = RTMGRP_LINK;
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
ERROR("Error, binding netlink socket: %s", strerror(errno));
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
static struct sub *sub_find(struct sub_head *subs, const char *name)
|
||||
{
|
||||
struct sub *sub;
|
||||
|
||||
TAILQ_FOREACH(sub, subs, entries) {
|
||||
if (strcmp(sub->name, name) == 0)
|
||||
return sub;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sub_delete(struct ev_loop *loop, struct sub_head *subs, struct sub *sub)
|
||||
{
|
||||
TAILQ_REMOVE(subs, sub, entries);
|
||||
ev_io_stop(loop, &sub->watcher);
|
||||
sr_unsubscribe(sub->sr_sub);
|
||||
free(sub);
|
||||
}
|
||||
|
||||
static json_t *json_get_ip_link(void)
|
||||
{
|
||||
char cmd[512] = {}; /* Size is arbitrary */
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "ip -s -d -j link show 2>/dev/null");
|
||||
|
||||
return json_get_output(cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* The 'fail' parameter is true for most calls to this function, except
|
||||
* when reading ethtool data (below).
|
||||
@@ -153,12 +78,12 @@ static int ly_add_yanger_data(const struct ly_ctx *ctx, struct lyd_node **parent
|
||||
return SR_ERR_SYS;
|
||||
}
|
||||
|
||||
if (!strcmp(model, "ietf-interfaces")) {
|
||||
if ((strcmp(model, "ietf-interfaces") == 0) && arg) {
|
||||
yanger_args[2] = "-p";
|
||||
yanger_args[3] = (char *)arg;
|
||||
}
|
||||
|
||||
fd = memfd_create("my_temp_file", MFD_CLOEXEC | MFD_NOEXEC_SEAL);
|
||||
fd = memfd_create("yanger_tmpfile", MFD_CLOEXEC | MFD_NOEXEC_SEAL);
|
||||
if (fd == -1) {
|
||||
ERROR("Error, unable to create memfd");
|
||||
return SR_ERR_SYS;
|
||||
@@ -201,18 +126,50 @@ static int ly_add_yanger_data(const struct ly_ctx *ctx, struct lyd_node **parent
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sr_ifaces_cb(sr_session_ctx_t *session, uint32_t, const char *path,
|
||||
const char *, const char *, uint32_t,
|
||||
struct lyd_node **parent, void *priv)
|
||||
static char *xpath_extract(const char *xpath, const char *key)
|
||||
{
|
||||
struct sub *sub = priv;
|
||||
char *res = NULL;
|
||||
const char *ptr;
|
||||
const char *end;
|
||||
|
||||
/* (also checks if key exist) */
|
||||
ptr = strstr(xpath, key);
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
|
||||
ptr += strlen(key);
|
||||
|
||||
end = strchr(ptr, '\'');
|
||||
if (!end) {
|
||||
ERROR("Can't find end quote for %s (sanity check)", key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((end - ptr) >= XPATH_MAX) {
|
||||
ERROR("Value for %s is to long (sanity check)", key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = calloc((end - ptr) + 1, sizeof(char));
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
strncpy(res, ptr, end - ptr);
|
||||
res[end - ptr] = '\0';
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int sr_iface_cb(sr_session_ctx_t *session, uint32_t, const char *model,
|
||||
const char *, const char *xpath, uint32_t,
|
||||
struct lyd_node **parent, __attribute__((unused)) void *priv)
|
||||
{
|
||||
char *ifname = NULL;
|
||||
const struct ly_ctx *ctx;
|
||||
sr_conn_ctx_t *con;
|
||||
char *ifname;
|
||||
int err;
|
||||
|
||||
ifname = &sub->name[3];
|
||||
DEBUG("Incoming query for xpath: %s, ifname %s", path, ifname);
|
||||
DEBUG("Incoming interface query for xpath: %s", xpath);
|
||||
|
||||
con = sr_session_get_connection(session);
|
||||
if (!con) {
|
||||
@@ -226,13 +183,37 @@ static int sr_ifaces_cb(sr_session_ctx_t *session, uint32_t, const char *path,
|
||||
return SR_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If ethtool fails, it just means this interface doesn't have
|
||||
* counters (in JSON format). Possibly because this board +
|
||||
* driver combo is not 100% supported yet. This is fine, no
|
||||
* need to break the operational datastore though.
|
||||
*/
|
||||
err = ly_add_yanger_data(ctx, parent, "ietf-interfaces", ifname, false);
|
||||
ifname = xpath_extract(xpath, "[name='");
|
||||
err = ly_add_yanger_data(ctx, parent, model, ifname, true);
|
||||
if (err)
|
||||
ERROR("Error adding interface yanger data");
|
||||
|
||||
sr_release_context(con);
|
||||
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
static int sr_generic_cb(sr_session_ctx_t *session, uint32_t, const char *model,
|
||||
const char *path, const char *, uint32_t,
|
||||
struct lyd_node **parent, __attribute__((unused)) void *priv)
|
||||
{
|
||||
const struct ly_ctx *ctx;
|
||||
sr_conn_ctx_t *con;
|
||||
sr_error_t err;
|
||||
|
||||
con = sr_session_get_connection(session);
|
||||
if (!con) {
|
||||
ERROR("Error, getting sr connection");
|
||||
return SR_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
ctx = sr_acquire_context(con);
|
||||
if (!ctx) {
|
||||
ERROR("Error, acquiring context");
|
||||
return SR_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
err = ly_add_yanger_data(ctx, parent, model, NULL, true);
|
||||
if (err)
|
||||
ERROR("Error adding yanger data");
|
||||
|
||||
@@ -272,36 +253,6 @@ static int sr_ospf_cb(sr_session_ctx_t *session, uint32_t, const char *,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sr_generic_cb(sr_session_ctx_t *session, uint32_t, const char *model,
|
||||
const char *path, const char *, uint32_t,
|
||||
struct lyd_node **parent, __attribute__((unused)) void *priv)
|
||||
{
|
||||
const struct ly_ctx *ctx;
|
||||
sr_conn_ctx_t *con;
|
||||
sr_error_t err;
|
||||
|
||||
DEBUG("Incoming query for xpath: %s", path);
|
||||
|
||||
con = sr_session_get_connection(session);
|
||||
if (!con) {
|
||||
ERROR("Error, getting sr connection");
|
||||
return SR_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
ctx = sr_acquire_context(con);
|
||||
if (!ctx) {
|
||||
ERROR("Error, acquiring context");
|
||||
return SR_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
err = ly_add_yanger_data(ctx, parent, model, NULL, true);
|
||||
if (err)
|
||||
ERROR("Error adding yanger data");
|
||||
|
||||
sr_release_context(con);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void sigint_cb(struct ev_loop *loop, struct ev_signal *, int)
|
||||
{
|
||||
@@ -320,29 +271,17 @@ static void sr_event_cb(struct ev_loop *, struct ev_io *w, int)
|
||||
sr_subscription_process_events(sub->sr_sub, NULL, NULL);
|
||||
}
|
||||
|
||||
static int subscribe(struct statd *statd, char *model, char *xpath, const char *name,
|
||||
static int subscribe(struct statd *statd, char *model, char *xpath,
|
||||
int (*cb)(sr_session_ctx_t *session, uint32_t, const char *, const char *,
|
||||
const char *, uint32_t, struct lyd_node **parent, void *priv))
|
||||
const char *, uint32_t, struct lyd_node **parent, void *priv))
|
||||
{
|
||||
struct sub *sub;
|
||||
int sr_ev_pipe;
|
||||
sr_error_t err;
|
||||
|
||||
sub = sub_find(&statd->subs, name);
|
||||
if (sub) {
|
||||
DEBUG("%s already subscribed", name);
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
sub = malloc(sizeof(struct sub));
|
||||
memset(sub, 0, sizeof(struct sub));
|
||||
|
||||
if (strlen(name) >= sizeof(sub->name)) {
|
||||
ERROR("Subscriber name is to long");
|
||||
free(sub);
|
||||
return SR_ERR_INTERNAL;
|
||||
}
|
||||
snprintf(sub->name, sizeof(sub->name), "%s", name);
|
||||
|
||||
DEBUG("Subscribe to events for \"%s\"", xpath);
|
||||
err = sr_oper_get_subscribe(statd->sr_ses, model, xpath, cb, sub,
|
||||
SR_SUBSCR_DEFAULT | SR_SUBSCR_NO_THREAD | SR_SUBSCR_DONE_ONLY,
|
||||
@@ -370,29 +309,12 @@ static int subscribe(struct statd *statd, char *model, char *xpath, const char *
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
static int sub_to_routes(struct statd *statd)
|
||||
static void sub_delete(struct ev_loop *loop, struct sub_head *subs, struct sub *sub)
|
||||
{
|
||||
return subscribe(statd, "ietf-routing", XPATH_ROUTING_TABLE, "routes", sr_generic_cb);
|
||||
}
|
||||
|
||||
static int sub_to_iface(struct statd *statd, const char *ifname)
|
||||
{
|
||||
char path[XPATH_MAX] = {};
|
||||
char name[IFNAMSIZ + 3];
|
||||
snprintf(name, sizeof(name), "if-%s", ifname);
|
||||
|
||||
/**
|
||||
* Skip internal interfaces (such as dsa0)
|
||||
*
|
||||
* NOTE: this is a good solution but it might be to slow if a lot of
|
||||
* new interfaces pops up at the same time. We don't want to delay
|
||||
* processing the netlink messages to much.
|
||||
*/
|
||||
if (ip_link_check_group(ifname, "internal") == 1)
|
||||
return SR_ERR_OK;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/interface[name='%s']", XPATH_IFACE_BASE, ifname);
|
||||
return subscribe(statd, "ietf-interfaces", path, name, sr_ifaces_cb);
|
||||
TAILQ_REMOVE(subs, sub, entries);
|
||||
ev_io_stop(loop, &sub->watcher);
|
||||
sr_unsubscribe(sub->sr_sub);
|
||||
free(sub);
|
||||
}
|
||||
|
||||
static void unsub_to_all(struct statd *statd)
|
||||
@@ -401,136 +323,30 @@ static void unsub_to_all(struct statd *statd)
|
||||
|
||||
while (!TAILQ_EMPTY(&statd->subs)) {
|
||||
sub = TAILQ_FIRST(&statd->subs);
|
||||
DEBUG("Unsubscribe from \"%s\" (all)", sub->name);
|
||||
sub_delete(statd->ev_loop, &statd->subs, sub);
|
||||
}
|
||||
}
|
||||
|
||||
static int unsub_to_name(struct statd *statd, char *name)
|
||||
static int subscribe_to_all(struct statd *statd)
|
||||
{
|
||||
struct sub *sub;
|
||||
DEBUG("Attempting to subscribe to all");
|
||||
|
||||
sub = sub_find(&statd->subs, name);
|
||||
if (!sub) {
|
||||
ERROR("Error, can't find indentity to delete (%s)", name);
|
||||
if (subscribe(statd, "ietf-routing", XPATH_ROUTING_TABLE, sr_generic_cb))
|
||||
return SR_ERR_INTERNAL;
|
||||
if (subscribe(statd, "ietf-interfaces", XPATH_IFACE_BASE, sr_iface_cb))
|
||||
return SR_ERR_INTERNAL;
|
||||
if (subscribe(statd, "ietf-routing", XPATH_ROUTING_OSPF, sr_ospf_cb))
|
||||
return SR_ERR_INTERNAL;
|
||||
if (subscribe(statd, "ietf-hardware", XPATH_HARDWARE_BASE, sr_generic_cb))
|
||||
return SR_ERR_INTERNAL;
|
||||
}
|
||||
DEBUG("Unsubscribe from \"%s\"", sub->name);
|
||||
sub_delete(statd->ev_loop, &statd->subs, sub);
|
||||
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
static int unsub_to_iface(struct statd *statd, char *ifname)
|
||||
{
|
||||
char name[IFNAMSIZ + 3];
|
||||
snprintf(name, sizeof(name), "if-%s", ifname);
|
||||
|
||||
return unsub_to_name(statd, name);
|
||||
}
|
||||
|
||||
static int nl_process_msg(struct nlmsghdr *nlh, struct statd *statd)
|
||||
{
|
||||
struct ifinfomsg *iface;
|
||||
struct rtattr *attr;
|
||||
int attr_len;
|
||||
|
||||
iface = NLMSG_DATA(nlh);
|
||||
attr = IFLA_RTA(iface);
|
||||
attr_len = IFLA_PAYLOAD(nlh);
|
||||
|
||||
for (; RTA_OK(attr, attr_len); attr = RTA_NEXT(attr, attr_len)) {
|
||||
if (attr->rta_type == IFLA_IFNAME) {
|
||||
char *ifname = (char *)RTA_DATA(attr);
|
||||
|
||||
if (nlh->nlmsg_type == RTM_NEWLINK)
|
||||
return sub_to_iface(statd, ifname);
|
||||
else if (nlh->nlmsg_type == RTM_DELLINK)
|
||||
return unsub_to_iface(statd, ifname);
|
||||
else
|
||||
return SR_ERR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ignore nl messages with no interface name */
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
static void nl_event_cb(struct ev_loop *, struct ev_io *w, int)
|
||||
{
|
||||
struct statd *statd = (struct statd *)w->data;
|
||||
char buf[NL_BUF_SIZE];
|
||||
struct nlmsghdr *nlh;
|
||||
int err;
|
||||
int len;
|
||||
|
||||
len = recv(statd->nl.sd, buf, sizeof(buf) - 1, 0);
|
||||
if (len < 0) {
|
||||
ERROR("Error, netlink recv failed: %s", strerror(errno));
|
||||
close(statd->nl.sd);
|
||||
/* NOTE: This is likely caused by a full kernel buffer, which
|
||||
* means we can't trust our list. So we exit hard and let finit
|
||||
* respawn us to handle this.
|
||||
*/
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* nl_process_msg() expects NULL terminated buffer */
|
||||
buf[len] = 0;
|
||||
|
||||
for (nlh = (struct nlmsghdr *)buf; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len)) {
|
||||
err = nl_process_msg(nlh, statd);
|
||||
if (err)
|
||||
ERROR("Error, processing netlink message: %s", sr_strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
static int sub_to_ifaces(struct statd *statd)
|
||||
{
|
||||
json_t *j_iface;
|
||||
json_t *j_root;
|
||||
size_t i;
|
||||
|
||||
j_root = json_get_ip_link();
|
||||
if (!j_root) {
|
||||
ERROR("Error, parsing ip-link JSON");
|
||||
return SR_ERR_SYS;
|
||||
}
|
||||
|
||||
json_array_foreach(j_root, i, j_iface) {
|
||||
json_t *j_ifname;
|
||||
int err;
|
||||
j_ifname = json_object_get(j_iface, "ifname");
|
||||
if (!json_is_string(j_ifname)) {
|
||||
ERROR("Got unexpected JSON type for 'ifname'");
|
||||
continue;
|
||||
}
|
||||
err = sub_to_iface(statd, json_string_value(j_ifname));
|
||||
if (err) {
|
||||
ERROR("Unable to subscribe to %s", json_string_value(j_ifname));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
json_decref(j_root);
|
||||
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
static int sub_to_hardware(struct statd *statd)
|
||||
{
|
||||
return subscribe(statd, "ietf-hardware", XPATH_HARDWARE_BASE, "hardware", sr_generic_cb);
|
||||
}
|
||||
|
||||
static int sub_to_ospf(struct statd *statd)
|
||||
{
|
||||
return subscribe(statd, "ietf-routing", XPATH_ROUTING_OSPF, "ospf", sr_ospf_cb);
|
||||
}
|
||||
|
||||
#ifdef CONTAINERS
|
||||
static int sub_to_container(struct statd *statd)
|
||||
{
|
||||
return subscribe(statd, "infix-containers", XPATH_CONTAIN_BASE, "container", sr_generic_cb);
|
||||
}
|
||||
if (subscribe(statd, "infix-containers", XPATH_CONTAIN_BASE, sr_generic_cb))
|
||||
return SR_ERR_INTERNAL;
|
||||
#endif
|
||||
INFO("Successfully subscribed to all models");
|
||||
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@@ -552,15 +368,8 @@ int main(int argc, char *argv[])
|
||||
TAILQ_INIT(&statd.subs);
|
||||
statd.ev_loop = EV_DEFAULT;
|
||||
|
||||
statd.nl.sd = nl_sock_init();
|
||||
if (statd.nl.sd < 0) {
|
||||
ERROR("Error, opening netlink socket");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
INFO("Status daemon starting");
|
||||
|
||||
set_sock_rcvbuf(statd.nl.sd, SOCK_RMEM_SIZE);
|
||||
|
||||
err = sr_connect(SR_CONN_DEFAULT, &sr_conn);
|
||||
if (err) {
|
||||
ERROR("Error, connecting to sysrepo: %s", sr_strerror(err));
|
||||
@@ -576,43 +385,12 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
DEBUG("Session started (%p)", statd.sr_ses);
|
||||
|
||||
DEBUG("Attempting to register existing interfaces");
|
||||
err = sub_to_ifaces(&statd);
|
||||
err = subscribe_to_all(&statd);
|
||||
if (err) {
|
||||
ERROR("Error, registering existing interfaces");
|
||||
sr_disconnect(sr_conn);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
err = sub_to_routes(&statd);
|
||||
if (err) {
|
||||
ERROR("Error register for IPv4 routes");
|
||||
sr_disconnect(sr_conn);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
err = sub_to_ospf(&statd);
|
||||
if (err) {
|
||||
ERROR("Error register for OSPF");
|
||||
sr_disconnect(sr_conn);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
err = sub_to_hardware(&statd);
|
||||
if (err) {
|
||||
ERROR("Error register for hardware status");
|
||||
sr_disconnect(sr_conn);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef CONTAINERS
|
||||
err = sub_to_container(&statd);
|
||||
if (err) {
|
||||
ERROR("Error registering infix-container status");
|
||||
sr_disconnect(sr_conn);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
ev_signal_init(&sigint_watcher, sigint_cb, SIGINT);
|
||||
sigint_watcher.data = &statd;
|
||||
ev_signal_start(statd.ev_loop, &sigint_watcher);
|
||||
@@ -621,10 +399,6 @@ int main(int argc, char *argv[])
|
||||
sigusr1_watcher.data = &statd;
|
||||
ev_signal_start(statd.ev_loop, &sigusr1_watcher);
|
||||
|
||||
ev_io_init(&statd.nl.watcher, nl_event_cb, statd.nl.sd, EV_READ);
|
||||
statd.nl.watcher.data = &statd;
|
||||
ev_io_start(statd.ev_loop, &statd.nl.watcher);
|
||||
|
||||
INFO("Status daemon entering main event loop");
|
||||
ev_run(statd.ev_loop, 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user