summaryrefslogtreecommitdiff
path: root/lib/if.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/if.c')
-rw-r--r--lib/if.c99
1 files changed, 67 insertions, 32 deletions
diff --git a/lib/if.c b/lib/if.c
index 41dc91a475..fe1d3ebb4a 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -48,6 +48,7 @@ DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters");
static void if_set_name(struct interface *ifp, const char *name);
static struct interface *if_lookup_by_ifindex(ifindex_t ifindex,
vrf_id_t vrf_id);
+static struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex);
static int if_cmp_func(const struct interface *, const struct interface *);
static int if_cmp_index_func(const struct interface *ifp1,
const struct interface *ifp2);
@@ -166,7 +167,6 @@ static struct interface *if_new(struct vrf *vrf)
ifp->name[0] = '\0';
ifp->vrf = vrf;
- ifp->vrf_id = vrf->vrf_id;
ifp->connected = list_new();
ifp->connected->del = ifp_connected_free;
@@ -237,8 +237,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
if (ifp->ifindex != IFINDEX_INTERNAL)
IFINDEX_RB_REMOVE(old_vrf, ifp);
- ifp->vrf_id = vrf_id;
- vrf = vrf_get(ifp->vrf_id, NULL);
+ vrf = vrf_get(vrf_id, NULL);
ifp->vrf = vrf;
if (ifp->name[0] != '\0')
@@ -302,9 +301,6 @@ void if_delete(struct interface **ifp)
if (ptr->ifindex != IFINDEX_INTERNAL)
IFINDEX_RB_REMOVE(vrf, ptr);
- if (!vrf_is_enabled(vrf))
- vrf_delete(vrf);
-
if_delete_retain(ptr);
list_delete(&ptr->connected);
@@ -423,7 +419,7 @@ struct interface *if_lookup_by_name_vrf(const char *name, struct vrf *vrf)
return RB_FIND(if_name_head, &vrf->ifaces_by_name, &if_tmp);
}
-struct interface *if_lookup_by_name_all_vrf(const char *name)
+static struct interface *if_lookup_by_name_all_vrf(const char *name)
{
struct vrf *vrf;
struct interface *ifp;
@@ -440,7 +436,7 @@ struct interface *if_lookup_by_name_all_vrf(const char *name)
return NULL;
}
-struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex)
+static struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex)
{
struct vrf *vrf;
struct interface *ifp;
@@ -457,36 +453,51 @@ struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex)
return NULL;
}
-/* Lookup interface by IP address. */
-struct interface *if_lookup_exact_address(const void *src, int family,
+/* Lookup interface by IP address.
+ *
+ * supersedes if_lookup_exact_address(), which didn't care about up/down
+ * state. but all users we have either only care if the address is local
+ * (=> use if_address_is_local() please), or care about UP interfaces before
+ * anything else
+ *
+ * to accept only UP interfaces, check if_is_up() on the returned ifp.
+ */
+struct interface *if_lookup_address_local(const void *src, int family,
vrf_id_t vrf_id)
{
struct vrf *vrf = vrf_lookup_by_id(vrf_id);
struct listnode *cnode;
- struct interface *ifp;
+ struct interface *ifp, *best_down = NULL;
struct prefix *p;
struct connected *c;
+ if (family != AF_INET && family != AF_INET6)
+ return NULL;
+
FOR_ALL_INTERFACES (vrf, ifp) {
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
p = c->address;
- if (p && (p->family == family)) {
- if (family == AF_INET) {
- if (IPV4_ADDR_SAME(
- &p->u.prefix4,
+ if (!p || p->family != family)
+ continue;
+
+ if (family == AF_INET) {
+ if (!IPV4_ADDR_SAME(&p->u.prefix4,
(struct in_addr *)src))
- return ifp;
- } else if (family == AF_INET6) {
- if (IPV6_ADDR_SAME(
- &p->u.prefix6,
+ continue;
+ } else if (family == AF_INET6) {
+ if (!IPV6_ADDR_SAME(&p->u.prefix6,
(struct in6_addr *)src))
- return ifp;
- }
+ continue;
}
+
+ if (if_is_up(ifp))
+ return ifp;
+ if (!best_down)
+ best_down = ifp;
}
}
- return NULL;
+ return best_down;
}
/* Lookup interface by IP address. */
@@ -591,7 +602,7 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
/* If it came from the kernel or by way of zclient,
* believe it and update the ifp accordingly.
*/
- if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
+ if (ifp->vrf->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
if_update_to_new_vrf(ifp, vrf_id);
return ifp;
@@ -604,7 +615,7 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
/* If it came from the kernel or by way of zclient,
* believe it and update the ifp accordingly.
*/
- if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
+ if (ifp->vrf->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
if_update_to_new_vrf(ifp, vrf_id);
return ifp;
@@ -630,7 +641,7 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex)
* If there is already an interface with this ifindex, we will collide
* on insertion, so don't even try.
*/
- if (if_lookup_by_ifindex(ifindex, ifp->vrf_id))
+ if (if_lookup_by_ifindex(ifindex, ifp->vrf->vrf_id))
return -1;
if (ifp->ifindex != IFINDEX_INTERNAL)
@@ -700,7 +711,7 @@ int if_is_no_ptm_operative(const struct interface *ifp)
}
/* Is this loopback interface ? */
-int if_is_loopback(const struct interface *ifp)
+int if_is_loopback_exact(const struct interface *ifp)
{
/* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
* but Y on platform N?
@@ -714,9 +725,10 @@ int if_is_vrf(const struct interface *ifp)
return CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
}
-bool if_is_loopback_or_vrf(const struct interface *ifp)
+/* Should this interface be treated as a loopback? */
+bool if_is_loopback(const struct interface *ifp)
{
- if (if_is_loopback(ifp) || if_is_vrf(ifp))
+ if (if_is_loopback_exact(ifp) || if_is_vrf(ifp))
return true;
return false;
@@ -793,8 +805,8 @@ static void if_dump(const struct interface *ifp)
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c))
zlog_info(
"Interface %s vrf %s(%u) index %d metric %d mtu %d mtu6 %d %s",
- ifp->name, ifp->vrf->name, ifp->vrf_id, ifp->ifindex,
- ifp->metric, ifp->mtu, ifp->mtu6,
+ ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
+ ifp->ifindex, ifp->metric, ifp->mtu, ifp->mtu6,
if_flag_dump(ifp->flags));
}
@@ -871,7 +883,7 @@ connected_log(struct connected *connected, char *str)
p = connected->address;
snprintf(logbuf, sizeof(logbuf), "%s interface %s vrf %s(%u) %s %pFX ",
- str, ifp->name, ifp->vrf->name, ifp->vrf_id,
+ str, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
prefix_family_str(p), p);
p = connected->destination;
@@ -1341,6 +1353,20 @@ static struct cmd_node interface_node = {
.prompt = "%s(config-if)# ",
};
+static int if_config_write_single(const struct lyd_node *dnode, void *arg)
+{
+ nb_cli_show_dnode_cmds(arg, dnode, false);
+
+ return YANG_ITER_CONTINUE;
+}
+
+static int if_nb_config_write(struct vty *vty)
+{
+ yang_dnode_iterate(if_config_write_single, vty, running_config->dnode,
+ "/frr-interface:lib/interface");
+ return 1;
+}
+
void if_cmd_init(int (*config_write)(struct vty *))
{
cmd_variable_handler_register(if_var_handlers);
@@ -1356,6 +1382,11 @@ void if_cmd_init(int (*config_write)(struct vty *))
install_element(INTERFACE_NODE, &no_interface_desc_cmd);
}
+void if_cmd_init_default(void)
+{
+ if_cmd_init(if_nb_config_write);
+}
+
void if_zapi_callbacks(int (*create)(struct interface *ifp),
int (*up)(struct interface *ifp),
int (*down)(struct interface *ifp),
@@ -1400,7 +1431,7 @@ static int lib_interface_create(struct nb_cb_create_args *args)
static int lib_interface_destroy(struct nb_cb_destroy_args *args)
{
struct interface *ifp;
-
+ struct vrf *vrf;
switch (args->event) {
case NB_EV_VALIDATE:
@@ -1416,9 +1447,13 @@ static int lib_interface_destroy(struct nb_cb_destroy_args *args)
break;
case NB_EV_APPLY:
ifp = nb_running_unset_entry(args->dnode);
+ vrf = ifp->vrf;
ifp->configured = false;
if_delete(&ifp);
+
+ if (!vrf_is_enabled(vrf))
+ vrf_delete(vrf);
break;
}