src/confd: initial operational data support for ietf-interfaces

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2023-04-17 14:09:24 +02:00
parent 5fe77fdbee
commit 4fe6a2aba7
4 changed files with 206 additions and 1 deletions
+1
View File
@@ -14,6 +14,7 @@
#include <augeas.h>
#include <libite/lite.h>
#include <libite/queue.h>
#include <libyang/libyang.h>
#include <sysrepo.h>
#include <sysrepo/values.h>
+165 -1
View File
@@ -1,22 +1,44 @@
/* SPDX-License-Identifier: BSD-3-Clause */
#include <net/if.h>
#include "core.h"
#include "srx_module.h"
#include "srx_val.h"
struct iface {
TAILQ_ENTRY(iface) link;
int ifindex;
char ifname[IFNAMSIZ];
char hwaddr[18];
short flags;
uint64_t speed;
short vid;
short pvid;
char upper[IFNAMSIZ];
};
static const char *iffeat[] = {
"if-mib",
NULL
};
static const char *ipfeat[] = {
"ipv4-non-contiguous-netmasks",
NULL
};
static const struct srx_module_requirement ietf_if_reqs[] = {
{ .dir = YANG_PATH_, .name = "ietf-interfaces", .rev = "2018-02-20" },
{ .dir = YANG_PATH_, .name = "ietf-interfaces", .rev = "2018-02-20", .features = iffeat },
{ .dir = YANG_PATH_, .name = "iana-if-type", .rev = "2017-01-19" },
{ .dir = YANG_PATH_, .name = "ietf-ip", .rev = "2018-02-22", .features = ipfeat },
{ NULL }
};
static TAILQ_HEAD(iflist, iface) iface_list = TAILQ_HEAD_INITIALIZER(iface_list);
static int inet_mask2len(char *netmask)
{
struct in_addr ina;
@@ -33,6 +55,104 @@ static int inet_mask2len(char *netmask)
return len;
}
static void ifprobe(void)
{
struct if_nameindex *if_list, *i;
if_list = if_nameindex();
if (!if_list) {
ERROR("failed if_nameindex(): %s", strerror(errno));
return;
}
for (i = if_list; !(i->if_index == 0 && i->if_name == NULL); i++) {
struct iface *iface;
if (!i->if_name || i->if_index == 0)
continue;
iface = calloc(1, sizeof(struct iface));
if (!iface) {
ERROR("out of memory");
return;
}
iface->ifindex = i->if_index;
strlcpy(iface->ifname, i->if_name, sizeof(iface->ifname));
/* XXX: add other data */
TAILQ_INSERT_TAIL(&iface_list, iface, link);
}
if_freenameindex(if_list);
}
#define INTERFACE_XPATH "/ietf-interfaces:interfaces/interface[name='%s']"
static void ifpopul(sr_session_ctx_t *session)
{
struct iface *iface;
int rc = 0;
TAILQ_FOREACH(iface, &iface_list, link) {
char xpath[sizeof(INTERFACE_XPATH) + IFNAMSIZ + 42];
sr_val_t val = { 0 };
snprintf(xpath, sizeof(xpath), INTERFACE_XPATH "/if-index", iface->ifname);
val.data.int32_val = iface->ifindex;
val.type = SR_INT32_T;
rc = sr_set_item(session, xpath, &val, 0);
if (rc)
ERROR("failed setting item %s", xpath);
snprintf(xpath, sizeof(xpath), INTERFACE_XPATH "/admin-status", iface->ifname);
val.data.enum_val = "up";
val.type = SR_ENUM_T;
rc = sr_set_item(session, xpath, &val, 0);
if (rc)
ERROR("failed setting item %s", xpath);
if (!iface->hwaddr[0]) /* e.g., loopback */
continue;
snprintf(xpath, sizeof(xpath), INTERFACE_XPATH "/phys-address", iface->ifname);
rc = sr_set_item_str(session, xpath, iface->hwaddr, 0, 0);
if (rc)
ERROR("failed setting item %s", xpath);
}
rc = sr_apply_changes(session, 0);
if (rc)
ERROR("faled: %s", sr_strerror(rc));
}
static void ifinit(sr_session_ctx_t *session)
{
struct iface *iface;
int rc = 0;
TAILQ_FOREACH(iface, &iface_list, link) {
char xpath[sizeof(INTERFACE_XPATH) + IFNAMSIZ + 42];
sr_val_t val;
snprintf(xpath, sizeof(xpath), INTERFACE_XPATH "/type", iface->ifname);
if (!strcmp("lo", iface->ifname))
val.data.string_val = "iana-if-type:softwareLoopback";
else if (!strncmp("eth", iface->ifname, 3))
val.data.string_val = "iana-if-type:ethernetCsmacd";
else
continue;
val.type = SR_IDENTITYREF_T;
rc = sr_set_item(session, xpath, &val, 0);
if (rc)
ERROR("failed setting item %s", xpath);
}
rc = sr_apply_changes(session, 0);
if (rc)
ERROR("faled: %s", sr_strerror(rc));
}
static int ifchange(sr_session_ctx_t *session, uint32_t sub_id, const char *module,
const char *xpath, sr_event_t event, unsigned request_id, void *priv)
{
@@ -133,6 +253,42 @@ fail:
return rc;
}
static int ifoper(sr_session_ctx_t *session, uint32_t sub_id, const char *module,
const char *path, const char *request_path, uint32_t request_id,
struct lyd_node **parent, void *priv)
{
char xpath[sizeof(INTERFACE_XPATH) + IFNAMSIZ + 42];
const struct ly_ctx *ctx;
struct iface *iface;
int first = 1;
int rc = 0;
ctx = sr_acquire_context(sr_session_get_connection(session));
TAILQ_FOREACH(iface, &iface_list, link) {
snprintf(xpath, sizeof(xpath), INTERFACE_XPATH, iface->ifname);
if ((rc = srx_set_item(ctx, parent, &first, xpath, "if-index", "%d", iface->ifindex)))
goto fail;
if ((rc = srx_set_item(ctx, parent, &first, xpath, "admin-status", "up")))
goto fail;
if ((rc = srx_set_item(ctx, parent, &first, xpath, "oper-status", "up")))
goto fail;
if (rc) {
fail:
ERROR("Failed building data tree, libyang error %d", rc);
sr_release_context(sr_session_get_connection(session));
return SR_ERR_INTERNAL;
}
}
sr_release_context(sr_session_get_connection(session));
return SR_ERR_OK;
}
int ietf_interfaces_init(struct confd *confd)
{
int rc;
@@ -141,7 +297,15 @@ int ietf_interfaces_init(struct confd *confd)
if (rc)
goto err;
ifprobe();
REGISTER_CHANGE(confd->session, "ietf-interfaces", "/ietf-interfaces:interfaces", 0, ifchange, confd, &confd->sub);
REGISTER_OPER(confd->session, "ietf-interfaces", "/ietf-interfaces:interfaces", ifoper, NULL, 0, &confd->sub);
sr_session_switch_ds(confd->session, SR_DS_OPERATIONAL);
ifpopul(confd->session);
sr_session_switch_ds(confd->session, SR_DS_RUNNING);
ifinit(confd->session);
return SR_ERR_OK;
err:
+37
View File
@@ -3,6 +3,43 @@
#include <stdarg.h>
#include "core.h"
int srx_set_item(const struct ly_ctx *ctx, struct lyd_node **parent, int *first,
char *xpath_base, char *node, const char *fmt, ...)
{
char xpath[strlen(xpath_base) + strlen(node) + 2];
va_list ap;
size_t len;
char *val;
int rc;
va_start(ap, fmt);
len = vsnprintf(NULL, 0, fmt, ap) + 1;
va_end(ap);
val = alloca(len);
if (!val)
return -1;
snprintf(xpath, sizeof(xpath), "%s/%s", xpath_base, node);
va_start(ap, fmt);
vsnprintf(val, len, fmt, ap);
va_end(ap);
DEBUG("Setting first:%d xpath %s to %s", *first, xpath, val);
if (*first)
rc = lyd_new_path(NULL, ctx, xpath, val, 0, parent);
else
rc = lyd_new_path(*parent, NULL, xpath, val, 0, NULL);
*first = 0;
if (rc)
ERROR("Failed building data tree, xpath %s, libyang error %d: %s",
xpath, rc, ly_errmsg(ctx));
return rc;
}
static int srx_vaget(sr_session_ctx_t *session, const char *fmt, va_list ap, sr_val_type_t type, sr_val_t **val, size_t *cnt)
{
va_list apdup;
+3
View File
@@ -8,6 +8,9 @@
#define SRX_GET_UINT8(s,v,fmt,...) srx_get_int(s, &v, SR_UINT8_T, fmt, ##__VA_ARGS__)
#define SRX_GET_UINT32(s,v,fmt,...) srx_get_int(s, &v, SR_UINT32_T, fmt, ##__VA_ARGS__)
int srx_set_item(const struct ly_ctx *ctx, struct lyd_node **parent, int *first, char *xpath_base,
char *node, const char *fmt, ...);
char *srx_get_str (sr_session_ctx_t *session, const char *fmt, ...);
int srx_get_int (sr_session_ctx_t *session, int *result, sr_val_type_t type, const char *fmt, ...);
int srx_get_bool (sr_session_ctx_t *session, const char *fmt, ...);