summaryrefslogtreecommitdiff
path: root/lib/if.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/if.c')
-rw-r--r--lib/if.c289
1 files changed, 183 insertions, 106 deletions
diff --git a/lib/if.c b/lib/if.c
index 378ca16e49..68724a65e9 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -29,6 +29,10 @@
#include "admin_group.h"
#include "lib/if_clippy.c"
+
+/* Set by the owner (zebra). */
+bool if_notify_oper_changes;
+
DEFINE_MTYPE_STATIC(LIB, IF, "Interface");
DEFINE_MTYPE_STATIC(LIB, IFDESC, "Intf Desc");
DEFINE_MTYPE_STATIC(LIB, CONNECTED, "Connected");
@@ -208,6 +212,104 @@ void if_down_via_zapi(struct interface *ifp)
hook_call(if_down, ifp);
}
+void if_update_state_metric(struct interface *ifp, uint32_t metric)
+{
+ if (ifp->metric == metric)
+ return;
+ ifp->metric = metric;
+ if (ifp->state && if_notify_oper_changes)
+ nb_op_updatef(ifp->state, "metric", "%u", ifp->metric);
+}
+
+void if_update_state_mtu(struct interface *ifp, uint mtu)
+{
+ if (ifp->mtu == mtu)
+ return;
+ ifp->mtu = mtu;
+ if (ifp->state && if_notify_oper_changes)
+ nb_op_updatef(ifp->state, "mtu", "%u", ifp->mtu);
+}
+
+void if_update_state_mtu6(struct interface *ifp, uint mtu)
+{
+ if (ifp->mtu6 == mtu)
+ return;
+ ifp->mtu6 = mtu;
+ if (ifp->state && if_notify_oper_changes)
+ nb_op_updatef(ifp->state, "mtu6", "%u", ifp->mtu);
+}
+
+void if_update_state_hw_addr(struct interface *ifp, const uint8_t *hw_addr, uint len)
+{
+ if (len == (uint)ifp->hw_addr_len && (len == 0 || !memcmp(hw_addr, ifp->hw_addr, len)))
+ return;
+ memcpy(ifp->hw_addr, hw_addr, len);
+ ifp->hw_addr_len = len;
+ if (ifp->state && if_notify_oper_changes)
+ nb_op_updatef(ifp->state, "phy-address", "%pEA", (struct ethaddr *)ifp->hw_addr);
+}
+
+void if_update_state_speed(struct interface *ifp, uint32_t speed)
+{
+ if (ifp->speed == speed)
+ return;
+ ifp->speed = speed;
+ if (ifp->state && if_notify_oper_changes)
+ nb_op_updatef(ifp->state, "speed", "%u", ifp->speed);
+}
+
+void if_update_state(struct interface *ifp)
+{
+ struct lyd_node *state = ifp->state;
+
+ if (!state || !if_notify_oper_changes)
+ return;
+
+ /*
+ * Remove top level container update when we have patch support, for now
+ * this keeps us from generating 6 separate REPLACE messages though.
+ */
+ // nb_op_update(state, ".", NULL);
+ nb_op_updatef(state, "if-index", "%d", ifp->ifindex);
+ nb_op_updatef(state, "mtu", "%u", ifp->mtu);
+ nb_op_updatef(state, "mtu6", "%u", ifp->mtu);
+ nb_op_updatef(state, "speed", "%u", ifp->speed);
+ nb_op_updatef(state, "metric", "%u", ifp->metric);
+ nb_op_updatef(state, "phy-address", "%pEA", (struct ethaddr *)ifp->hw_addr);
+}
+
+static void if_update_state_remove(struct interface *ifp)
+{
+ if (!if_notify_oper_changes || ifp->name[0] == 0)
+ return;
+
+ if (vrf_is_backend_netns())
+ nb_op_update_delete_pathf(NULL, "/frr-interface:lib/interface[name=\"%s:%s\"]/state",
+ ifp->vrf->name, ifp->name);
+ else
+ nb_op_update_delete_pathf(NULL, "/frr-interface:lib/interface[name=\"%s\"]/state",
+ ifp->name);
+ if (ifp->state) {
+ lyd_free_all(ifp->state);
+ ifp->state = NULL;
+ }
+}
+
+static void if_update_state_add(struct interface *ifp)
+{
+ if (!if_notify_oper_changes || ifp->name[0] == 0)
+ return;
+
+ if (vrf_is_backend_netns())
+ ifp->state = nb_op_update_pathf(NULL,
+ "/frr-interface:lib/interface[name=\"%s:%s\"]/state",
+ NULL, ifp->vrf->name, ifp->name);
+ else
+ ifp->state = nb_op_update_pathf(NULL,
+ "/frr-interface:lib/interface[name=\"%s\"]/state",
+ NULL, ifp->name);
+}
+
static struct interface *if_create_name(const char *name, struct vrf *vrf)
{
struct interface *ifp;
@@ -216,7 +318,11 @@ static struct interface *if_create_name(const char *name, struct vrf *vrf)
if_set_name(ifp, name);
+ if (if_notify_oper_changes && ifp->state)
+ if_update_state(ifp);
+
hook_call(if_add, ifp);
+
return ifp;
}
@@ -228,8 +334,10 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
/* remove interface from old master vrf list */
old_vrf = ifp->vrf;
- if (ifp->name[0] != '\0')
+ if (ifp->name[0] != '\0') {
IFNAME_RB_REMOVE(old_vrf, ifp);
+ if_update_state_remove(ifp);
+ }
if (ifp->ifindex != IFINDEX_INTERNAL)
IFINDEX_RB_REMOVE(old_vrf, ifp);
@@ -237,8 +345,11 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
vrf = vrf_get(vrf_id, NULL);
ifp->vrf = vrf;
- if (ifp->name[0] != '\0')
+ if (ifp->name[0] != '\0') {
IFNAME_RB_INSERT(vrf, ifp);
+ if_update_state_add(ifp);
+ if_update_state(ifp);
+ }
if (ifp->ifindex != IFINDEX_INTERNAL)
IFINDEX_RB_INSERT(vrf, ifp);
@@ -280,6 +391,8 @@ void if_delete(struct interface **ifp)
XFREE(MTYPE_IFDESC, ptr->desc);
+ if_update_state_remove(ptr);
+
XFREE(MTYPE_IF, ptr);
*ifp = NULL;
}
@@ -303,7 +416,6 @@ static struct interface *if_lookup_by_ifindex(ifindex_t ifindex,
struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
{
switch (vrf_get_backend()) {
- case VRF_BACKEND_UNKNOWN:
case VRF_BACKEND_NETNS:
return(if_lookup_by_ifindex(ifindex, vrf_id));
case VRF_BACKEND_VRF_LITE:
@@ -573,7 +685,6 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
struct vrf *vrf;
switch (vrf_get_backend()) {
- case VRF_BACKEND_UNKNOWN:
case VRF_BACKEND_NETNS:
vrf = vrf_get(vrf_id, vrf_name);
assert(vrf);
@@ -630,6 +741,9 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex)
ifp->ifindex = ifindex;
+ if (if_notify_oper_changes)
+ nb_op_updatef(ifp->state, "if-index", "%d", ifp->ifindex);
+
if (ifp->ifindex != IFINDEX_INTERNAL) {
/*
* This should never happen, since we checked if there was
@@ -648,13 +762,17 @@ static void if_set_name(struct interface *ifp, const char *name)
if (if_cmp_name_func(ifp->name, name) == 0)
return;
- if (ifp->name[0] != '\0')
+ if (ifp->name[0] != '\0') {
IFNAME_RB_REMOVE(ifp->vrf, ifp);
+ if_update_state_remove(ifp);
+ }
strlcpy(ifp->name, name, sizeof(ifp->name));
- if (ifp->name[0] != '\0')
+ if (ifp->name[0] != '\0') {
IFNAME_RB_INSERT(ifp->vrf, ifp);
+ if_update_state_add(ifp);
+ }
}
/* Does interface up ? */
@@ -858,47 +976,6 @@ struct nbr_connected *nbr_connected_check(struct interface *ifp,
return NULL;
}
-/* Print if_addr structure. */
-static void __attribute__((unused))
-connected_log(struct connected *connected, char *str)
-{
- struct prefix *p;
- struct interface *ifp;
- char logbuf[BUFSIZ];
- char buf[BUFSIZ];
-
- ifp = connected->ifp;
- p = connected->address;
-
- snprintf(logbuf, sizeof(logbuf), "%s interface %s vrf %s(%u) %s %pFX ",
- str, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
- prefix_family_str(p), p);
-
- p = connected->destination;
- if (p) {
- strlcat(logbuf, inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
- BUFSIZ);
- }
- zlog_info("%s", logbuf);
-}
-
-/* Print if_addr structure. */
-static void __attribute__((unused))
-nbr_connected_log(struct nbr_connected *connected, char *str)
-{
- struct prefix *p;
- struct interface *ifp;
- char logbuf[BUFSIZ];
-
- ifp = connected->ifp;
- p = connected->address;
-
- snprintf(logbuf, sizeof(logbuf), "%s interface %s %s %pFX ", str,
- ifp->name, prefix_family_str(p), p);
-
- zlog_info("%s", logbuf);
-}
-
/* count the number of connected addresses that are in the given family */
unsigned int connected_count_by_family(struct interface *ifp, int family)
{
@@ -1649,90 +1726,90 @@ static int lib_interface_description_destroy(struct nb_cb_destroy_args *args)
return NB_OK;
}
-/*
- * XPath: /frr-interface:lib/interface/vrf
- */
-static struct yang_data *
-lib_interface_vrf_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error __return_ok(const struct nb_node *nb_node, const void *list_entry,
+ struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
-
- return yang_data_new_string(args->xpath, ifp->vrf->name);
+ return NB_OK;
}
/*
- * XPath: /frr-interface:lib/interface/state/if-index
+ * XPath: /frr-interface:lib/interface/vrf
*/
-static struct yang_data *
-lib_interface_state_if_index_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error lib_interface_vrf_get(const struct nb_node *nb_node, const void *list_entry,
+ struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
+ const struct lysc_node *snode = nb_node->snode;
+ const struct interface *ifp = list_entry;
- return yang_data_new_int32(args->xpath, ifp->ifindex);
+ if (lyd_new_term(parent, snode->module, snode->name, ifp->vrf->name, LYD_NEW_PATH_UPDATE,
+ NULL))
+ return NB_ERR_RESOURCE;
+ return NB_OK;
}
/*
- * XPath: /frr-interface:lib/interface/state/mtu
+ * XPath: /frr-interface:lib/interface/state/if-index
*/
-static struct yang_data *
-lib_interface_state_mtu_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error lib_interface_state_if_index_get(const struct nb_node *nb_node,
+ const void *list_entry,
+ struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
+ const struct lysc_node *snode = nb_node->snode;
+ const struct interface *ifp = list_entry;
+ int32_t value = ifp->ifindex;
- return yang_data_new_uint32(args->xpath, ifp->mtu);
+ if (lyd_new_term_bin(parent, snode->module, snode->name, &value, sizeof(value),
+ LYD_NEW_PATH_UPDATE, NULL))
+ return NB_ERR_RESOURCE;
+ return NB_OK;
}
/*
- * XPath: /frr-interface:lib/interface/state/mtu6
+ * XPath: /frr-interface:lib/interface/state/mtu[6]
*/
-static struct yang_data *
-lib_interface_state_mtu6_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error lib_interface_state_mtu_get(const struct nb_node *nb_node,
+ const void *list_entry, struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
+ const struct lysc_node *snode = nb_node->snode;
+ const struct interface *ifp = list_entry;
+ uint32_t value = ifp->mtu;
- return yang_data_new_uint32(args->xpath, ifp->mtu6);
+ if (lyd_new_term_bin(parent, snode->module, snode->name, &value, sizeof(value),
+ LYD_NEW_PATH_UPDATE, NULL))
+ return NB_ERR_RESOURCE;
+ return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/state/speed
*/
-static struct yang_data *
-lib_interface_state_speed_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error lib_interface_state_speed_get(const struct nb_node *nb_node,
+ const void *list_entry, struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
+ const struct lysc_node *snode = nb_node->snode;
+ const struct interface *ifp = list_entry;
+ uint32_t value = ifp->speed;
- return yang_data_new_uint32(args->xpath, ifp->speed);
+ if (lyd_new_term_bin(parent, snode->module, snode->name, &value, sizeof(value),
+ LYD_NEW_PATH_UPDATE, NULL))
+ return NB_ERR_RESOURCE;
+ return NB_OK;
}
/*
* XPath: /frr-interface:lib/interface/state/metric
*/
-static struct yang_data *
-lib_interface_state_metric_get_elem(struct nb_cb_get_elem_args *args)
+static enum nb_error lib_interface_state_metric_get(const struct nb_node *nb_node,
+ const void *list_entry, struct lyd_node *parent)
{
- const struct interface *ifp = args->list_entry;
-
- return yang_data_new_uint32(args->xpath, ifp->metric);
-}
+ const struct lysc_node *snode = nb_node->snode;
+ const struct interface *ifp = list_entry;
+ uint32_t value = ifp->metric;
-/*
- * XPath: /frr-interface:lib/interface/state/flags
- */
-static struct yang_data *
-lib_interface_state_flags_get_elem(struct nb_cb_get_elem_args *args)
-{
- /* TODO: implement me. */
- return NULL;
-}
-
-/*
- * XPath: /frr-interface:lib/interface/state/type
- */
-static struct yang_data *
-lib_interface_state_type_get_elem(struct nb_cb_get_elem_args *args)
-{
- /* TODO: implement me. */
- return NULL;
+ if (lyd_new_term_bin(parent, snode->module, snode->name, &value, sizeof(value),
+ LYD_NEW_PATH_UPDATE, NULL))
+ return NB_ERR_RESOURCE;
+ return NB_OK;
}
/*
@@ -1779,49 +1856,49 @@ const struct frr_yang_module_info frr_interface_info = {
{
.xpath = "/frr-interface:lib/interface/vrf",
.cbs = {
- .get_elem = lib_interface_vrf_get_elem,
+ .get = lib_interface_vrf_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/if-index",
.cbs = {
- .get_elem = lib_interface_state_if_index_get_elem,
+ .get = lib_interface_state_if_index_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/mtu",
.cbs = {
- .get_elem = lib_interface_state_mtu_get_elem,
+ .get = lib_interface_state_mtu_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/mtu6",
.cbs = {
- .get_elem = lib_interface_state_mtu6_get_elem,
+ .get = lib_interface_state_mtu_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/speed",
.cbs = {
- .get_elem = lib_interface_state_speed_get_elem,
+ .get = lib_interface_state_speed_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/metric",
.cbs = {
- .get_elem = lib_interface_state_metric_get_elem,
+ .get = lib_interface_state_metric_get,
}
},
{
.xpath = "/frr-interface:lib/interface/state/flags",
.cbs = {
- .get_elem = lib_interface_state_flags_get_elem,
+ .get = __return_ok,
}
},
{
.xpath = "/frr-interface:lib/interface/state/type",
.cbs = {
- .get_elem = lib_interface_state_type_get_elem,
+ .get = __return_ok,
}
},
{