diff options
Diffstat (limited to 'zebra/rt_netlink.c')
-rw-r--r-- | zebra/rt_netlink.c | 109 |
1 files changed, 87 insertions, 22 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e4505de3..131b37a6 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -38,6 +38,8 @@ #include "thread.h" #include "privs.h" #include "vrf.h" +#include "nexthop.h" +#include "vty.h" #include "zebra/zserv.h" #include "zebra/rt.h" @@ -851,12 +853,12 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (gate) { if (index) - nexthop_ipv4_ifindex_add (rib, gate, src, index); + rib_nexthop_ipv4_ifindex_add (rib, gate, src, index); else - nexthop_ipv4_add (rib, gate, src); + rib_nexthop_ipv4_add (rib, gate, src); } else - nexthop_ifindex_add (rib, index); + rib_nexthop_ifindex_add (rib, index); len -= NLMSG_ALIGN(rtnh->rtnh_len); rtnh = RTNH_NEXT(rtnh); @@ -907,6 +909,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int len; struct rtmsg *rtm; struct rtattr *tb[RTA_MAX + 1]; + u_char zebra_flags = 0; char anyaddr[16] = { 0 }; @@ -964,6 +967,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE) return 0; + if (rtm->rtm_protocol == RTPROT_ZEBRA) + SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE); if (rtm->rtm_src_len != 0) { @@ -1065,12 +1070,12 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (gate) { if (index) - nexthop_ipv4_ifindex_add (rib, gate, src, index); + rib_nexthop_ipv4_ifindex_add (rib, gate, src, index); else - nexthop_ipv4_add (rib, gate, src); + rib_nexthop_ipv4_add (rib, gate, src); } else - nexthop_ifindex_add (rib, index); + rib_nexthop_ifindex_add (rib, index); len -= NLMSG_ALIGN(rtnh->rtnh_len); rtnh = RTNH_NEXT(rtnh); @@ -1083,8 +1088,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, } } else - rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, - SAFI_UNICAST); + rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, gate, + index, vrf_id, SAFI_UNICAST); } #ifdef HAVE_IPV6 @@ -1108,7 +1113,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, table, 0, mtu, 0, SAFI_UNICAST); else - rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, + rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, gate, index, vrf_id, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ @@ -1470,7 +1475,8 @@ _netlink_route_build_singlepath( struct nexthop *nexthop, struct nlmsghdr *nlmsg, struct rtmsg *rtmsg, - size_t req_size) + size_t req_size, + int cmd) { if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) rtmsg->rtm_flags |= RTNH_F_ONLINK; @@ -1479,7 +1485,11 @@ _netlink_route_build_singlepath( { addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen); - if (nexthop->src.ipv4.s_addr) + + if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) + addattr_l (nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv4, bytelen); + else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) addattr_l (nlmsg, req_size, RTA_PREFSRC, &nexthop->src.ipv4, bytelen); @@ -1512,7 +1522,10 @@ _netlink_route_build_singlepath( { addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); - if (nexthop->src.ipv4.s_addr) + if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) + addattr_l (nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv4, bytelen); + else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) addattr_l (nlmsg, req_size, RTA_PREFSRC, &nexthop->src.ipv4, bytelen); @@ -1573,8 +1586,10 @@ _netlink_route_build_multipath( &nexthop->gate.ipv4, bytelen); rtnh->rtnh_len += sizeof (struct rtattr) + bytelen; - if (nexthop->src.ipv4.s_addr) - *src = &nexthop->src; + if (nexthop->rmap_src.ipv4.s_addr) + *src = &nexthop->rmap_src; + else if (nexthop->src.ipv4.s_addr) + *src = &nexthop->src; if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (%s): " @@ -1606,8 +1621,12 @@ _netlink_route_build_multipath( || nexthop->type == NEXTHOP_TYPE_IFNAME) { rtnh->rtnh_ifindex = nexthop->ifindex; - if (nexthop->src.ipv4.s_addr) + + if (nexthop->rmap_src.ipv4.s_addr) + *src = &nexthop->rmap_src; + else if (nexthop->src.ipv4.s_addr) *src = &nexthop->src; + if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (%s): " "nexthop via if %u", routedesc, nexthop->ifindex); @@ -1670,6 +1689,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib) int discard; int family = PREFIX_FAMILY(p); const char *routedesc; + int setsrc = 0; + union g_addr src; struct { @@ -1708,6 +1729,10 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib) req.r.rtm_type = RTN_UNREACHABLE; else assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */ + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: Adding discard route for family %s\n", + __FUNCTION__, family == AF_INET ? "IPv4" : "IPv6"); } else req.r.rtm_type = RTN_UNICAST; @@ -1773,7 +1798,23 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib) for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) { if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; + { + /* This only works for IPv4 now */ + if (!setsrc) + { + if (nexthop->rmap_src.ipv4.s_addr != 0) + { + src.ipv4 = nexthop->rmap_src.ipv4; + setsrc = 1; + } + else if (nexthop->src.ipv4.s_addr != 0) + { + src.ipv4 = nexthop->src.ipv4; + setsrc = 1; + } + } + continue; + } if ((cmd == RTM_NEWROUTE && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) @@ -1785,7 +1826,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib) _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf); _netlink_route_build_singlepath(routedesc, bytelen, nexthop, &req.n, &req.r, - sizeof req); + sizeof req, cmd); if (cmd == RTM_NEWROUTE) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); @@ -1794,13 +1835,15 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib) break; } } + if (setsrc && (cmd == RTM_NEWROUTE)) + addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen); } else { char buf[NL_PKT_BUF_SIZE]; struct rtattr *rta = (void *) buf; struct rtnexthop *rtnh; - union g_addr *src = NULL; + union g_addr *src1 = NULL; rta->rta_type = RTA_MULTIPATH; rta->rta_len = RTA_LENGTH (0); @@ -1813,7 +1856,23 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib) break; if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; + { + /* This only works for IPv4 now */ + if (!setsrc) + { + if (nexthop->rmap_src.ipv4.s_addr != 0) + { + src.ipv4 = nexthop->rmap_src.ipv4; + setsrc = 1; + } + else if (nexthop->src.ipv4.s_addr != 0) + { + src.ipv4 = nexthop->src.ipv4; + setsrc = 1; + } + } + continue; + } if ((cmd == RTM_NEWROUTE && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) @@ -1826,15 +1885,21 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib) _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf); _netlink_route_build_multipath(routedesc, bytelen, - nexthop, rta, rtnh, &src); + nexthop, rta, rtnh, &src1); rtnh = RTNH_NEXT (rtnh); if (cmd == RTM_NEWROUTE) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); + + if (!setsrc && src1) + { + src.ipv4 = src1->ipv4; + setsrc = 1; + } } } - if (src) - addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen); + if (setsrc && (cmd == RTM_NEWROUTE)) + addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen); if (rta->rta_len > RTA_LENGTH (0)) addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta), |