summaryrefslogtreecommitdiffstats
path: root/zebra/rt_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/rt_netlink.c')
-rw-r--r--zebra/rt_netlink.c109
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),