This simplifies the API for the following blackhole rework.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label")
/* check if nexthops are same, non-recursive */
-int nexthop_same_no_recurse(struct nexthop *next1, struct nexthop *next2)
+int nexthop_same_no_recurse(const struct nexthop *next1,
+ const struct nexthop *next2)
{
if (next1->type != next2->type)
return 0;
void nexthop_del_labels(struct nexthop *);
extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type);
-extern int nexthop_same_no_recurse(struct nexthop *next1,
- struct nexthop *next2);
+extern int nexthop_same_no_recurse(const struct nexthop *next1,
+ const struct nexthop *next2);
extern int nexthop_labels_match(struct nexthop *nh1, struct nexthop *nh2);
extern const char *nexthop2str(struct nexthop *nexthop, char *str, int size);
void connected_up_ipv4(struct interface *ifp, struct connected *ifc)
{
struct prefix p;
+ struct nexthop nh = {
+ .type = NEXTHOP_TYPE_IFINDEX,
+ .ifindex = ifp->ifindex,
+ };
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
return;
return;
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);
+ &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);
+ &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
void connected_down_ipv4(struct interface *ifp, struct connected *ifc)
{
struct prefix p;
+ struct nexthop nh = {
+ .type = NEXTHOP_TYPE_IFINDEX,
+ .ifindex = ifp->ifindex,
+ };
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
return;
/* 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);
+ &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);
+ 0, &p, NULL, &nh, 0, 0);
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
void connected_up_ipv6(struct interface *ifp, struct connected *ifc)
{
struct prefix p;
+ struct nexthop nh = {
+ .type = NEXTHOP_TYPE_IFINDEX,
+ .ifindex = ifp->ifindex,
+ };
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
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);
+ &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
void connected_down_ipv6(struct interface *ifp, struct connected *ifc)
{
struct prefix p;
+ struct nexthop nh = {
+ .type = NEXTHOP_TYPE_IFINDEX,
+ .ifindex = ifp->ifindex,
+ };
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
return;
return;
rib_delete(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
- 0, &p, NULL, NULL, ifp->ifindex, 0, 0);
+ 0, &p, NULL, &nh, 0, 0);
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
union sockunion dest, mask, gate;
char ifname[INTERFACE_NAMSIZ + 1];
short ifnlen = 0;
+ struct nexthop nh;
zebra_flags = 0;
*/
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);
+ ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p,
+ NULL, 0, 0);
+
+ memset(&nh, 0, sizeof(nh));
+ nh.type = NEXTHOP_TYPE_IPV4;
+ nh.gate.ipv4 = gate.sin;
- union g_addr ggate = {.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,
- &ggate, NULL, 0, 0, 0, 0, 0);
+ &nh, 0, 0, 0, 0);
else
rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &ggate, 0, 0, 0);
+ &nh, 0, 0);
}
if (dest.sa.sa_family == AF_INET6) {
/* One day we might have a debug section here like one in the
*/
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);
+ ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p,
+ NULL, NULL, 0, 0);
+
+ memset(&nh, 0, sizeof(nh));
+ nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
+ : NEXTHOP_TYPE_IPV6;
+ nh.gate.ipv6 = gate.sin6;
+ nh.ifindex = ifindex;
- union g_addr ggate = {.ipv6 = gate.sin6.sin6_addr};
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,
- &ggate, NULL, ifindex, 0, 0, 0, 0);
+ &nh, 0, 0, 0, 0);
else
rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
- &ggate, ifindex, 0, 0);
+ &nh, 0, 0);
}
}
struct route_entry *newre;
struct route_entry *same;
struct prefix p;
- struct nexthop *nhop;
- union g_addr *gate;
route_map_result_t ret = RMAP_MATCH;
if (rmap_name)
if (re->nexthop_num == 1) {
- nhop = re->nexthop;
- if (nhop->type == NEXTHOP_TYPE_IFINDEX)
- gate = NULL;
- else
- gate = (union g_addr *)&nhop->gate.ipv4;
-
rib_add(AFI_IP, SAFI_UNICAST, re->vrf_id,
ZEBRA_ROUTE_TABLE, re->table, 0, &p,
- NULL, gate,
- (union g_addr *)&nhop->src.ipv4,
- nhop->ifindex, zebrad.rtm_table_default,
+ NULL, re->nexthop,
+ zebrad.rtm_table_default,
re->metric, re->mtu,
zebra_import_table_distance[AFI_IP]
[re->table]);
p.u.prefix4 = rn->p.u.prefix4;
rib_delete(AFI_IP, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE,
- re->table, re->flags, &p, NULL, NULL, 0,
+ re->table, re->flags, &p, NULL, NULL,
zebrad.rtm_table_default, re->metric);
}
/* DD: Add IPv6 code */
* also implicitly withdraw equal prefix of same type. */
extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
u_short instance, int flags, struct prefix *p,
- struct prefix_ipv6 *src_p, union g_addr *gate,
- union g_addr *src, ifindex_t ifindex, u_int32_t table_id,
- u_int32_t metric, u_int32_t mtu, u_char distance);
+ struct prefix_ipv6 *src_p, const struct nexthop *nh,
+ u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
+ u_char distance);
extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *,
struct prefix_ipv6 *src_p, struct route_entry *);
extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
u_short instance, int flags, struct prefix *p,
- struct prefix_ipv6 *src_p, union g_addr *gate,
- ifindex_t ifindex, u_int32_t table_id,
- u_int32_t metric);
+ struct prefix_ipv6 *src_p, const struct nexthop *nh,
+ u_int32_t table_id, u_int32_t metric);
extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t,
union g_addr *,
afi = AFI_IP6;
if (h->nlmsg_type == RTM_NEWROUTE) {
- if (!tb[RTA_MULTIPATH])
+ if (!tb[RTA_MULTIPATH]) {
+ struct nexthop nh;
+ size_t sz = (afi == AFI_IP) ? 4 : 16;
+
+ memset(&nh, 0, sizeof(nh));
+ if (index && !gate)
+ nh.type = NEXTHOP_TYPE_IFINDEX;
+ else if (index && gate)
+ nh.type = (afi == AFI_IP)
+ ? NEXTHOP_TYPE_IPV4_IFINDEX
+ : NEXTHOP_TYPE_IPV6_IFINDEX;
+ else if (!index && gate)
+ nh.type = (afi == AFI_IP)
+ ? NEXTHOP_TYPE_IPV4
+ : NEXTHOP_TYPE_IPV6;
+ else
+ nh.type = NEXTHOP_TYPE_BLACKHOLE;
+ nh.ifindex = index;
+ if (prefsrc)
+ memcpy(&nh.src, prefsrc, sz);
+ if (gate)
+ memcpy(&nh.gate, gate, sz);
rib_add(afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
- 0, flags, &p, NULL, gate, prefsrc, index, table,
- metric, mtu, 0);
- else {
+ 0, flags, &p, NULL, &nh, table, metric, mtu, 0);
+ } else {
/* This is a multipath route */
struct route_entry *re;
NULL, re);
}
} else {
- if (!tb[RTA_MULTIPATH])
+ if (!tb[RTA_MULTIPATH]) {
+ struct nexthop nh;
+ size_t sz = (afi == AFI_IP) ? 4 : 16;
+
+ memset(&nh, 0, sizeof(nh));
+ if (index && !gate)
+ nh.type = NEXTHOP_TYPE_IFINDEX;
+ else if (index && gate)
+ nh.type = (afi == AFI_IP)
+ ? NEXTHOP_TYPE_IPV4_IFINDEX
+ : NEXTHOP_TYPE_IPV6_IFINDEX;
+ else if (!index && gate)
+ nh.type = (afi == AFI_IP)
+ ? NEXTHOP_TYPE_IPV4
+ : NEXTHOP_TYPE_IPV6;
+ else
+ nh.type = NEXTHOP_TYPE_BLACKHOLE;
+ nh.ifindex = index;
+ if (gate)
+ memcpy(&nh.gate, gate, sz);
rib_delete(afi, SAFI_UNICAST, vrf_id,
- ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, gate,
- index, table, metric);
- else {
- struct rtnexthop *rtnh =
- (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
-
- len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
-
- for (;;) {
- if (len < (int)sizeof(*rtnh)
- || rtnh->rtnh_len > len)
- break;
-
- gate = NULL;
- if (rtnh->rtnh_len > sizeof(*rtnh)) {
- memset(tb, 0, sizeof(tb));
- netlink_parse_rtattr(
- tb, RTA_MAX, RTNH_DATA(rtnh),
- rtnh->rtnh_len - sizeof(*rtnh));
- if (tb[RTA_GATEWAY])
- gate = RTA_DATA(
- tb[RTA_GATEWAY]);
- }
-
- if (gate)
- rib_delete(afi, SAFI_UNICAST, vrf_id,
- ZEBRA_ROUTE_KERNEL, 0, flags,
- &p, NULL, gate, index,
- table, metric);
-
- len -= NLMSG_ALIGN(rtnh->rtnh_len);
- rtnh = RTNH_NEXT(rtnh);
- }
+ ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, &nh,
+ table, metric);
+ } else {
+ /* XXX: need to compare the entire list of nexthops
+ * here for NLM_F_APPEND stupidity */
+ rib_delete(afi, SAFI_UNICAST, vrf_id,
+ ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL,
+ NULL, table, metric);
}
}
static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry)
{
struct prefix prefix;
- struct in_addr tmpaddr, gateway;
- union g_addr *ggateway;
+ struct in_addr tmpaddr;
+ struct nexthop nh;
u_char zebra_flags = 0;
if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE)
tmpaddr.s_addr = routeEntry->ipRouteMask;
prefix.prefixlen = ip_masklen(tmpaddr);
- gateway.s_addr = routeEntry->ipRouteNextHop;
- ggateway = (union g_addr *)&gateway;
+ memset(&nh, 0, sizeof(nh));
+ nh.type = NEXTHOP_TYPE_IPV4;
+ nh.gate.ipv4.s_addr = routeEntry->ipRouteNextHop;
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
- zebra_flags, &prefix, NULL, ggateway, NULL, 0, 0, 0, 0, 0);
+ zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0);
}
void route_read(struct zebra_ns *zns)
void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
u_short instance, int flags, struct prefix *p,
- struct prefix_ipv6 *src_p, union g_addr *gate,
- ifindex_t ifindex, u_int32_t table_id,
- u_int32_t metric)
+ struct prefix_ipv6 *src_p, const struct nexthop *nh,
+ u_int32_t table_id, u_int32_t metric)
{
struct route_table *table;
struct route_node *rn;
struct route_entry *re;
struct route_entry *fib = NULL;
struct route_entry *same = NULL;
- struct nexthop *nexthop;
+ struct nexthop *rtnh;
char buf2[INET6_ADDRSTRLEN];
assert(!src_p || afi == AFI_IP6);
if (re->type == ZEBRA_ROUTE_KERNEL &&
re->metric != metric)
continue;
- if (re->type == ZEBRA_ROUTE_CONNECT && (nexthop = re->nexthop)
- && nexthop->type == NEXTHOP_TYPE_IFINDEX) {
- if (nexthop->ifindex != ifindex)
+ if (re->type == ZEBRA_ROUTE_CONNECT && (rtnh = re->nexthop)
+ && rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
+ if (rtnh->ifindex != nh->ifindex)
continue;
if (re->refcnt) {
re->refcnt--;
}
/* Make sure that the route found has the same gateway. */
else {
- if (gate == NULL) {
+ if (nh == NULL) {
same = re;
break;
}
- for (ALL_NEXTHOPS(re->nexthop, nexthop))
- if (IPV4_ADDR_SAME(&nexthop->gate.ipv4, &gate->ipv4)
- || IPV6_ADDR_SAME(&nexthop->gate.ipv6,
- gate)) {
+ for (ALL_NEXTHOPS(re->nexthop, rtnh))
+ if (nexthop_same_no_recurse(rtnh, nh)) {
same = re;
break;
}
}
if (allow_delete) {
/* Unset flags. */
- for (nexthop = fib->nexthop; nexthop;
- nexthop = nexthop->next)
- UNSET_FLAG(nexthop->flags,
+ for (rtnh = fib->nexthop; rtnh;
+ rtnh = rtnh->next)
+ UNSET_FLAG(rtnh->flags,
NEXTHOP_FLAG_FIB);
UNSET_FLAG(fib->status,
}
} else {
if (IS_ZEBRA_DEBUG_RIB) {
- if (gate)
+ if (nh)
rnode_debug(
rn, vrf_id,
"via %s ifindex %d type %d "
"doesn't exist in rib",
inet_ntop(
- family2afi(afi), gate,
+ family2afi(afi), &nh->gate,
buf2,
INET_ADDRSTRLEN), /* FIXME
*/
- ifindex, type);
+ nh->ifindex, type);
else
rnode_debug(
rn, vrf_id,
- "ifindex %d type %d doesn't exist in rib",
- ifindex, type);
+ "type %d doesn't exist in rib",
+ type);
}
route_unlock_node(rn);
return;
int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
int flags, struct prefix *p, struct prefix_ipv6 *src_p,
- union g_addr *gate, union g_addr *src, ifindex_t ifindex,
- u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
- u_char distance)
+ const struct nexthop *nh, u_int32_t table_id, u_int32_t metric,
+ u_int32_t mtu, u_char distance)
{
struct route_entry *re;
struct route_entry *same = NULL;
struct route_table *table;
struct route_node *rn;
- struct nexthop *nexthop;
+ struct nexthop *rtnh;
assert(!src_p || afi == AFI_IP6);
break;
}
/* Duplicate system route comes in. */
- else if ((nexthop = re->nexthop)
- && nexthop->type == NEXTHOP_TYPE_IFINDEX
- && nexthop->ifindex == ifindex
+ else if ((rtnh = re->nexthop)
+ && rtnh->type == NEXTHOP_TYPE_IFINDEX
+ && rtnh->ifindex == nh->ifindex
&& !CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
re->refcnt++;
return 0;
re->nexthop_num = 0;
re->uptime = time(NULL);
- /* Nexthop settings. */
- if (gate) {
- if (afi == AFI_IP6) {
- if (ifindex)
- route_entry_nexthop_ipv6_ifindex_add(
- re, &gate->ipv6, ifindex);
- else
- route_entry_nexthop_ipv6_add(re, &gate->ipv6);
- } else {
- if (ifindex)
- route_entry_nexthop_ipv4_ifindex_add(
- re, &gate->ipv4, &src->ipv4, ifindex);
- else
- route_entry_nexthop_ipv4_add(re, &gate->ipv4,
- &src->ipv4);
- }
- } else
- route_entry_nexthop_ifindex_add(re, ifindex);
+ rtnh = nexthop_new();
+ *rtnh = *nh;
+ route_entry_nexthop_add(re, rtnh);
/* If this route is kernel route, set FIB flag to the route. */
if (RIB_SYSTEM_ROUTE(re))
- for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next)
- SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+ for (rtnh = re->nexthop; rtnh; rtnh = rtnh->next)
+ SET_FLAG(rtnh->flags, NEXTHOP_FLAG_FIB);
/* Link new rib to node.*/
if (IS_ZEBRA_DEBUG_RIB) {