summaryrefslogtreecommitdiff
path: root/zebra/connected.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/connected.c')
-rw-r--r--zebra/connected.c360
1 files changed, 173 insertions, 187 deletions
diff --git a/zebra/connected.c b/zebra/connected.c
index 701314f246..77a560c6bd 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -54,10 +54,7 @@ static void connected_withdraw(struct connected *ifc)
if (ifc->address->family == AF_INET)
if_subnet_delete(ifc->ifp, ifc);
- if (ifc->address->family == AF_INET)
- connected_down_ipv4(ifc->ifp, ifc);
- else
- connected_down_ipv6(ifc->ifp, ifc);
+ connected_down(ifc->ifp, ifc);
UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
}
@@ -92,16 +89,15 @@ static void connected_announce(struct interface *ifp, struct connected *ifc)
zebra_interface_address_add_update(ifp, ifc);
if (if_is_operative(ifp)) {
- if (ifc->address->family == AF_INET)
- connected_up_ipv4(ifp, ifc);
- else
- connected_up_ipv6(ifp, ifc);
+ connected_up(ifp, ifc);
}
}
/* If same interface address is already exist... */
-struct connected *connected_check(struct interface *ifp, struct prefix *p)
+struct connected *connected_check(struct interface *ifp,
+ union prefixconstptr pu)
{
+ const struct prefix *p = pu.p;
struct connected *ifc;
struct listnode *node;
@@ -112,6 +108,33 @@ struct connected *connected_check(struct interface *ifp, struct prefix *p)
return NULL;
}
+/* same, but with peer address */
+struct connected *connected_check_ptp(struct interface *ifp,
+ union prefixconstptr pu,
+ union prefixconstptr du)
+{
+ const struct prefix *p = pu.p;
+ const struct prefix *d = du.p;
+ struct connected *ifc;
+ struct listnode *node;
+
+ /* ignore broadcast addresses */
+ if (p->prefixlen != IPV4_MAX_PREFIXLEN)
+ d = NULL;
+
+ for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
+ if (!prefix_same(ifc->address, p))
+ continue;
+ if (!CONNECTED_PEER(ifc) && !d)
+ return ifc;
+ if (CONNECTED_PEER(ifc) && d
+ && prefix_same(ifc->destination, d))
+ return ifc;
+ }
+
+ return NULL;
+}
+
/* Check if two ifc's describe the same address in the same state */
static int connected_same(struct connected *ifc1, struct connected *ifc2)
{
@@ -145,7 +168,8 @@ static void connected_update(struct interface *ifp, struct connected *ifc)
struct connected *current;
/* Check same connected route. */
- if ((current = connected_check(ifp, (struct prefix *)ifc->address))) {
+ current = connected_check_ptp(ifp, ifc->address, ifc->destination);
+ if (current) {
if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
@@ -174,43 +198,70 @@ static void connected_update(struct interface *ifp, struct connected *ifc)
}
/* Called from if_up(). */
-void connected_up_ipv4(struct interface *ifp, struct connected *ifc)
+void connected_up(struct interface *ifp, struct connected *ifc)
{
+ afi_t afi;
struct prefix p;
+ struct nexthop nh = {
+ .type = NEXTHOP_TYPE_IFINDEX, .ifindex = ifp->ifindex,
+ };
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
return;
- PREFIX_COPY_IPV4((struct prefix_ipv4 *)&p, CONNECTED_PREFIX(ifc));
+ PREFIX_COPY(&p, CONNECTED_PREFIX(ifc));
/* Apply mask to the network. */
apply_mask(&p);
- /* In case of connected address is 0.0.0.0/0 we treat it tunnel
- address. */
- if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
+ afi = family2afi(p.family);
+
+ switch (afi) {
+ case AFI_IP:
+ /*
+ * In case of connected address is 0.0.0.0/0 we treat it tunnel
+ * address.
+ */
+ if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
+ return;
+ break;
+ case AFI_IP6:
+#ifndef LINUX
+ /* XXX: It is already done by rib_bogus_ipv6 within rib_add */
+ if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
+ return;
+#endif
+ break;
+ default:
+ zlog_warn("Received unknown AFI: %s", afi2str(afi));
return;
+ break;
+ }
- rib_add(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
- &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric,
- 0, 0);
+ rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
+ &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
- rib_add(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
- &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric,
- 0, 0);
+ rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
+ &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- "%u: IF %s IPv4 address add/up, scheduling RIB processing",
- ifp->vrf_id, ifp->name);
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
+ char buf[PREFIX_STRLEN];
+
+ zlog_debug("%u: IF %s address %s add/up, scheduling RIB processing",
+ ifp->vrf_id, ifp->name,
+ prefix2str(&p, buf, sizeof(buf)));
+ }
rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
/* Schedule LSP forwarding entries for processing, if appropriate. */
if (ifp->vrf_id == VRF_DEFAULT) {
- if (IS_ZEBRA_DEBUG_MPLS)
- zlog_debug(
- "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
- ifp->vrf_id, ifp->name);
+ if (IS_ZEBRA_DEBUG_MPLS) {
+ char buf[PREFIX_STRLEN];
+
+ zlog_debug("%u: IF %s IP %s address add/up, scheduling MPLS processing",
+ ifp->vrf_id, ifp->name,
+ prefix2str(&p, buf, sizeof(buf)));
+ }
mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
}
}
@@ -238,7 +289,8 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
p = prefix_ipv4_new();
p->family = AF_INET;
p->prefix = *addr;
- p->prefixlen = prefixlen;
+ p->prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
+ : prefixlen;
ifc->address = (struct prefix *)p;
/* If there is broadcast or peer address. */
@@ -303,127 +355,136 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
connected_update(ifp, ifc);
}
-void connected_down_ipv4(struct interface *ifp, struct connected *ifc)
+void connected_down(struct interface *ifp, struct connected *ifc)
{
+ afi_t afi;
struct prefix p;
+ struct nexthop nh = {
+ .type = NEXTHOP_TYPE_IFINDEX, .ifindex = ifp->ifindex,
+ };
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
return;
- PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
+ PREFIX_COPY(&p, CONNECTED_PREFIX(ifc));
/* Apply mask to the network. */
apply_mask(&p);
- /* In case of connected address is 0.0.0.0/0 we treat it tunnel
- address. */
- if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
- return;
+ afi = family2afi(p.family);
- /* Same logic as for connected_up_ipv4(): push the changes into the
- * head. */
- rib_delete(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
- &p, NULL, NULL, ifp->ifindex, 0, 0);
+ switch (afi) {
+ case AFI_IP:
+ /*
+ * In case of connected address is 0.0.0.0/0 we treat it tunnel
+ * address.
+ */
+ if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
+ return;
+ break;
+ case AFI_IP6:
+ if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
+ return;
+ break;
+ default:
+ zlog_info("Unknown AFI: %s", afi2str(afi));
+ break;
+ }
+
+ /*
+ * Same logic as for connected_up(): push the changes into the
+ * head.
+ */
+ rib_delete(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
+ &p, NULL, &nh, 0, 0);
+
+ rib_delete(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
+ 0, &p, NULL, &nh, 0, 0);
- rib_delete(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
- 0, &p, NULL, NULL, ifp->ifindex, 0, 0);
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
+ char buf[PREFIX_STRLEN];
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- "%u: IF %s IPv4 address down, scheduling RIB processing",
- ifp->vrf_id, ifp->name);
+ zlog_debug("%u: IF %s IP %s address down, scheduling RIB processing",
+ ifp->vrf_id, ifp->name,
+ prefix2str(&p, buf, sizeof(buf)));
+ }
rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
/* Schedule LSP forwarding entries for processing, if appropriate. */
if (ifp->vrf_id == VRF_DEFAULT) {
- if (IS_ZEBRA_DEBUG_MPLS)
- zlog_debug(
- "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
- ifp->vrf_id, ifp->name);
+ if (IS_ZEBRA_DEBUG_MPLS) {
+ char buf[PREFIX_STRLEN];
+
+ zlog_debug("%u: IF %s IP %s address down, scheduling MPLS processing",
+ ifp->vrf_id, ifp->name,
+ prefix2str(&p, buf, sizeof(buf)));
+ }
mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
}
}
-/* Delete connected IPv4 route to the interface. */
-void connected_delete_ipv4(struct interface *ifp, int flags,
- struct in_addr *addr, u_char prefixlen,
- struct in_addr *broad)
+static void connected_delete_helper(struct connected *ifc, struct prefix *p)
{
- struct prefix_ipv4 p;
- struct connected *ifc;
+ struct interface *ifp;
- memset(&p, 0, sizeof(struct prefix_ipv4));
- p.family = AF_INET;
- p.prefix = *addr;
- p.prefixlen = prefixlen;
-
- ifc = connected_check(ifp, (struct prefix *)&p);
if (!ifc)
return;
+ ifp = ifc->ifp;
connected_withdraw(ifc);
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- "%u: IF %s IPv4 address del, scheduling RIB processing",
- ifp->vrf_id, ifp->name);
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
+ char buf[PREFIX_STRLEN];
+ zlog_debug("%u: IF %s IP %s address del, scheduling RIB processing",
+ ifp->vrf_id, ifp->name,
+ prefix2str(p, buf, sizeof(buf)));
+ }
rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
/* Schedule LSP forwarding entries for processing, if appropriate. */
if (ifp->vrf_id == VRF_DEFAULT) {
- if (IS_ZEBRA_DEBUG_MPLS)
- zlog_debug(
- "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
- ifp->vrf_id, ifp->name);
+ if (IS_ZEBRA_DEBUG_MPLS) {
+ char buf[PREFIX_STRLEN];
+
+ zlog_debug("%u: IF %s IP %s address delete, scheduling MPLS processing",
+ ifp->vrf_id, ifp->name,
+ prefix2str(p, buf, sizeof(buf)));
+ }
mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
}
}
-void connected_up_ipv6(struct interface *ifp, struct connected *ifc)
+/* Delete connected IPv4 route to the interface. */
+void connected_delete_ipv4(struct interface *ifp, int flags,
+ struct in_addr *addr, u_char prefixlen,
+ struct in_addr *broad)
{
- struct prefix p;
-
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
- return;
-
- PREFIX_COPY_IPV6((struct prefix_ipv6 *)&p, CONNECTED_PREFIX(ifc));
-
- /* Apply mask to the network. */
- apply_mask(&p);
-
-#ifndef LINUX
- /* XXX: It is already done by rib_bogus_ipv6 within rib_add */
- if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
- return;
-#endif
-
- rib_add(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
- &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric,
- 0, 0);
-
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- "%u: IF %s IPv6 address down, scheduling RIB processing",
- ifp->vrf_id, ifp->name);
+ struct prefix p, d;
+ struct connected *ifc;
- rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
+ memset(&p, 0, sizeof(struct prefix));
+ p.family = AF_INET;
+ p.u.prefix4 = *addr;
+ p.prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
+ : prefixlen;
- /* Schedule LSP forwarding entries for processing, if appropriate. */
- if (ifp->vrf_id == VRF_DEFAULT) {
- if (IS_ZEBRA_DEBUG_MPLS)
- zlog_debug(
- "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
- ifp->vrf_id, ifp->name);
- mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
- }
+ if (broad) {
+ memset(&d, 0, sizeof(struct prefix));
+ d.family = AF_INET;
+ d.u.prefix4 = *broad;
+ d.prefixlen = prefixlen;
+ ifc = connected_check_ptp(ifp, &p, &d);
+ } else
+ ifc = connected_check_ptp(ifp, &p, NULL);
+
+ connected_delete_helper(ifc, &p);
}
/* Add connected IPv6 route to the interface. */
void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
- u_char prefixlen, struct in6_addr *broad,
- const char *label)
+ u_char prefixlen, const char *label)
{
struct prefix_ipv6 *p;
struct connected *ifc;
@@ -446,29 +507,6 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
p->prefixlen = prefixlen;
ifc->address = (struct prefix *)p;
- /* If there is broadcast or peer address. */
- if (broad) {
- if (IN6_IS_ADDR_UNSPECIFIED(broad))
- zlog_warn(
- "warning: %s called for interface %s with unspecified "
- "destination address; ignoring!",
- __func__, ifp->name);
- else {
- p = prefix_ipv6_new();
- p->family = AF_INET6;
- IPV6_ADDR_COPY(&p->prefix, broad);
- p->prefixlen = prefixlen;
- ifc->destination = (struct prefix *)p;
- }
- }
- if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination) {
- zlog_warn(
- "warning: %s called for interface %s "
- "with peer flag set, but no peer address supplied",
- __func__, ifp->name);
- UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
- }
-
/* Label of this address. */
if (label)
ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
@@ -486,72 +524,20 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
connected_update(ifp, ifc);
}
-void connected_down_ipv6(struct interface *ifp, struct connected *ifc)
-{
- struct prefix p;
-
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
- return;
-
- PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
-
- apply_mask(&p);
-
- if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
- return;
-
- rib_delete(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
- 0, &p, NULL, NULL, ifp->ifindex, 0, 0);
-
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- "%u: IF %s IPv6 address down, scheduling RIB processing",
- ifp->vrf_id, ifp->name);
-
- rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
-
- /* Schedule LSP forwarding entries for processing, if appropriate. */
- if (ifp->vrf_id == VRF_DEFAULT) {
- if (IS_ZEBRA_DEBUG_MPLS)
- zlog_debug(
- "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
- ifp->vrf_id, ifp->name);
- mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
- }
-}
-
void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address,
- u_char prefixlen, struct in6_addr *broad)
+ u_char prefixlen)
{
- struct prefix_ipv6 p;
+ struct prefix p;
struct connected *ifc;
- memset(&p, 0, sizeof(struct prefix_ipv6));
+ memset(&p, 0, sizeof(struct prefix));
p.family = AF_INET6;
- memcpy(&p.prefix, address, sizeof(struct in6_addr));
+ memcpy(&p.u.prefix6, address, sizeof(struct in6_addr));
p.prefixlen = prefixlen;
- ifc = connected_check(ifp, (struct prefix *)&p);
- if (!ifc)
- return;
-
- connected_withdraw(ifc);
-
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- "%u: IF %s IPv6 address del, scheduling RIB processing",
- ifp->vrf_id, ifp->name);
-
- rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
+ ifc = connected_check(ifp, &p);
- /* Schedule LSP forwarding entries for processing, if appropriate. */
- if (ifp->vrf_id == VRF_DEFAULT) {
- if (IS_ZEBRA_DEBUG_MPLS)
- zlog_debug(
- "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
- ifp->vrf_id, ifp->name);
- mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
- }
+ connected_delete_helper(ifc, &p);
}
int connected_is_unnumbered(struct interface *ifp)