#define strmatch(a,b) (!strcmp((a), (b)))
/* Zebra message flags */
+
+/*
+ * Cause Zebra to consider this routes nexthops recursively
+ */
#define ZEBRA_FLAG_ALLOW_RECURSION 0x01
+/*
+ * This is a route that is read in on startup that was left around
+ * from a previous run of FRR
+ */
#define ZEBRA_FLAG_SELFROUTE 0x02
-#define ZEBRA_FLAG_IBGP 0x08
-#define ZEBRA_FLAG_SELECTED 0x10
-#define ZEBRA_FLAG_STATIC 0x40
-#define ZEBRA_FLAG_SCOPE_LINK 0x100
-#define ZEBRA_FLAG_FIB_OVERRIDE 0x200
-#define ZEBRA_FLAG_EVPN_ROUTE 0x400
-#define ZEBRA_FLAG_RR_USE_DISTANCE 0x800
-#define ZEBRA_FLAG_ONLINK 0x1000
-/* ZEBRA_FLAG_BLACKHOLE was 0x04 */
-/* ZEBRA_FLAG_REJECT was 0x80 */
+/*
+ * This flag is used to tell Zebra that the BGP route being passed
+ * down is a IBGP route
+ */
+#define ZEBRA_FLAG_IBGP 0x04
+/*
+ * This is a route that has been selected for FIB installation.
+ * This flag is set in zebra and can be passed up to routing daemons
+ */
+#define ZEBRA_FLAG_SELECTED 0x08
+/*
+ * This is a route that we are telling Zebra that this route *must*
+ * win and will be installed even over ZEBRA_FLAG_SELECTED
+ */
+#define ZEBRA_FLAG_FIB_OVERRIDE 0x10
+/*
+ * This flag tells Zebra that the route is a EVPN route and should
+ * be treated specially
+ */
+#define ZEBRA_FLAG_EVPN_ROUTE 0x20
+/*
+ * This flag tells Zebra that it should treat the distance passed
+ * down as an additional discriminator for route selection of the
+ * route entry. This mainly is used for backup static routes.
+ */
+#define ZEBRA_FLAG_RR_USE_DISTANCE 0x40
+/*
+ * This flag tells Zebra that the passed down route is ONLINK and the
+ * kernel install flag for it should be turned on
+ */
+#define ZEBRA_FLAG_ONLINK 0x80
/* Zebra FEC flags. */
#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x1
char ifname[INTERFACE_NAMSIZ + 1];
short ifnlen = 0;
struct nexthop nh;
+ struct prefix p;
+ ifindex_t ifindex = 0;
+ afi_t afi;
zebra_flags = 0;
if (flags & RTF_PROTO1)
SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
- /* This is persistent route. */
- if (flags & RTF_STATIC)
- SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC);
-
memset(&nh, 0, sizeof(nh));
nh.vrf_id = VRF_DEFAULT;
nh.bh_type = BLACKHOLE_NULL;
}
- if (dest.sa.sa_family == AF_INET) {
- struct prefix p;
+ /*
+ * Ignore our own messages.
+ */
+ if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
+ return;
+ if (dest.sa.sa_family == AF_INET) {
+ afi = AFI_IP;
p.family = AF_INET;
p.u.prefix4 = dest.sin.sin_addr;
if (flags & RTF_HOST)
else
p.prefixlen = ip_masklen(mask.sin.sin_addr);
- /* Catch self originated messages and match them against our
- * current RIB.
- * At the same time, ignore unconfirmed messages, they should be
- * tracked
- * by rtm_write() and kernel_rtm_ipv4().
- */
- if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) {
- char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN];
- int ret;
- if (!IS_ZEBRA_DEBUG_RIB)
- return;
- ret = rib_lookup_ipv4_route((struct prefix_ipv4 *)&p,
- &gate, VRF_DEFAULT);
- prefix2str(&p, buf, sizeof(buf));
- switch (rtm->rtm_type) {
- case RTM_ADD:
- case RTM_GET:
- case RTM_CHANGE:
- /* The kernel notifies us about a new route in
- FIB created by us.
- Do we have a correspondent entry in our RIB?
- */
- switch (ret) {
- case ZEBRA_RIB_NOTFOUND:
- zlog_debug(
- "%s: %s %s: desync: RR isn't yet in RIB, while already in FIB",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- break;
- case ZEBRA_RIB_FOUND_CONNECTED:
- case ZEBRA_RIB_FOUND_NOGATE:
- inet_ntop(AF_INET, &gate.sin.sin_addr,
- gate_buf, INET_ADDRSTRLEN);
- zlog_debug(
- "%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf, gate_buf);
- break;
- case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR
- */
- zlog_debug(
- "%s: %s %s: done Ok", __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- return;
- break;
- }
- break;
- case RTM_DELETE:
- /* The kernel notifies us about a route deleted
- by us. Do we still
- have it in the RIB? Do we have anything
- instead? */
- switch (ret) {
- case ZEBRA_RIB_FOUND_EXACT:
- zlog_debug(
- "%s: %s %s: desync: RR is still in RIB, while already not in FIB",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- break;
- case ZEBRA_RIB_FOUND_CONNECTED:
- case ZEBRA_RIB_FOUND_NOGATE:
- zlog_debug(
- "%s: %s %s: desync: RR is still in RIB, plus gate differs",
- __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- break;
- case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */
- zlog_debug(
- "%s: %s %s: done Ok", __func__,
- lookup_msg(rtm_type_str,
- rtm->rtm_type, NULL),
- buf);
- rib_lookup_and_dump(
- (struct prefix_ipv4 *)&p,
- VRF_DEFAULT);
- return;
- break;
- }
- break;
- default:
- zlog_debug(
- "%s: %s: warning: loopback RTM of type %s received",
- __func__, buf,
- lookup_msg(rtm_type_str, rtm->rtm_type,
- NULL));
- }
- return;
- }
-
- /* Change, delete the old prefix, we have no further information
- * to specify the route really
- */
- if (rtm->rtm_type == RTM_CHANGE)
- rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- NULL, 0, 0, 0, true);
-
if (!nh.type) {
nh.type = NEXTHOP_TYPE_IPV4;
nh.gate.ipv4 = gate.sin.sin_addr;
}
-
- if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
- || rtm->rtm_type == RTM_CHANGE)
- rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, 0, 0);
- else
- rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, true);
- }
- if (dest.sa.sa_family == AF_INET6) {
- /* One day we might have a debug section here like one in the
- * IPv4 case above. Just ignore own messages at the moment.
- */
- if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
- return;
- struct prefix p;
- ifindex_t ifindex = 0;
-
+ } else if (dest.sa.sa_family == AF_INET6) {
+ afi = AFI_IP6;
p.family = AF_INET6;
p.u.prefix6 = dest.sin6.sin6_addr;
if (flags & RTF_HOST)
}
#endif /* KAME */
- /* CHANGE: delete the old prefix, we have no further information
- * to specify the route really
- */
- if (rtm->rtm_type == RTM_CHANGE)
- rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- NULL, 0, 0, 0, true);
-
if (!nh.type) {
nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
: NEXTHOP_TYPE_IPV6;
nh.gate.ipv6 = gate.sin6.sin6_addr;
nh.ifindex = ifindex;
}
+ } else
+ return;
- if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
- || rtm->rtm_type == RTM_CHANGE)
- rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, 0, 0);
- else
- rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
- ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &nh, 0, 0, 0, true);
- }
+ /*
+ * CHANGE: delete the old prefix, we have no further information
+ * to specify the route really
+ */
+ if (rtm->rtm_type == RTM_CHANGE)
+ rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
+ 0, zebra_flags, &p, NULL, NULL, 0, 0, 0, true);
+ if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
+ || rtm->rtm_type == RTM_CHANGE)
+ rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
+ zebra_flags, &p, NULL, &nh, 0, 0, 0, 0, 0);
+ else
+ rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
+ 0, zebra_flags, &p, NULL, &nh, 0, 0, 0, true);
}
/* Interface function for the kernel routing table updates. Support
return NULL;
}
-/*
- * This clone function, unlike its original rib_lookup_ipv4(), checks
- * if specified IPv4 route record (prefix/mask -> gate) exists in
- * the whole RIB and has ROUTE_ENTRY_SELECTED_FIB set.
- *
- * Return values:
- * -1: error
- * 0: exact match found
- * 1: a match was found with a different gate
- * 2: connected route found
- * 3: no matches found
- */
-int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate,
- vrf_id_t vrf_id)
-{
- struct route_table *table;
- struct route_node *rn;
- struct route_entry *match = NULL;
- struct nexthop *nexthop;
- int nexthops_active;
- rib_dest_t *dest;
-
- /* Lookup table. */
- table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
- if (!table)
- return ZEBRA_RIB_LOOKUP_ERROR;
-
- /* Scan the RIB table for exactly matching RIB entry. */
- rn = route_node_lookup(table, (struct prefix *)p);
-
- /* No route for this prefix. */
- if (!rn)
- return ZEBRA_RIB_NOTFOUND;
-
- /* Unlock node. */
- route_unlock_node(rn);
- dest = rib_dest_from_rnode(rn);
-
- /* Find out if a "selected" RR for the discovered RIB entry exists ever.
- */
- if (dest && dest->selected_fib
- && !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
- match = dest->selected_fib;
-
- /* None such found :( */
- if (!match)
- return ZEBRA_RIB_NOTFOUND;
-
- if (match->type == ZEBRA_ROUTE_CONNECT)
- return ZEBRA_RIB_FOUND_CONNECTED;
-
- /* Ok, we have a cood candidate, let's check it's nexthop list... */
- nexthops_active = 0;
- for (ALL_NEXTHOPS(match->ng, nexthop))
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
- nexthops_active = 1;
- if (nexthop->gate.ipv4.s_addr == sockunion2ip(qgate))
- return ZEBRA_RIB_FOUND_EXACT;
- if (IS_ZEBRA_DEBUG_RIB) {
- char gate_buf[INET_ADDRSTRLEN],
- qgate_buf[INET_ADDRSTRLEN];
- inet_ntop(AF_INET, &nexthop->gate.ipv4.s_addr,
- gate_buf, INET_ADDRSTRLEN);
- inet_ntop(AF_INET, &sockunion2ip(qgate),
- qgate_buf, INET_ADDRSTRLEN);
- zlog_debug("%s: qgate == %s, %s == %s",
- __func__, qgate_buf,
- nexthop->rparent ? "rgate" : "gate",
- gate_buf);
- }
- }
-
- if (nexthops_active)
- return ZEBRA_RIB_FOUND_NOGATE;
-
- return ZEBRA_RIB_NOTFOUND;
-}
-
#define RIB_SYSTEM_ROUTE(R) \
((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)