mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-30 20:43:02 +02:00
src/confd: initial operational data support for ietf-interfaces
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, ...);
|
||||
|
||||
Reference in New Issue
Block a user