summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2015-05-19 17:47:24 -0700
committerDonald Sharp <sharpd@cumulusnetworks.com>2015-05-19 17:47:24 -0700
commitc52ef59fedc4ce81afc842990980c8384d6dfce3 (patch)
tree116d33d4320e53fc8d96ee5b5893fd7b98c04c8f
parentb5d58c32bb74cf2fa0aa43a07396b06765d54ac0 (diff)
zebra-set-src-routemap.patch
Honor setting source via route map and pushing that to the kernel. With recursive routes, the ability to set the source IP address of a route via a routemap has been broken. This patch fixes that. To allow route map to set a source and then to unapply the route map and have the source be taken out, I've introduced a new field in the nexthop data structure called rmap_src. This field is zero'd before invoking the route map apply function. Today, no protocol daemon specifies the src in its route update to zebra. If that happens, I didn't want to stomp on it and so have left the src field intact instead of reusing that for the routemap to play with. Signed-off-by: Dinesh G Dutt <ddutt@cumulusnetworks.com>
-rw-r--r--lib/nexthop.h1
-rw-r--r--zebra/rt_netlink.c82
-rw-r--r--zebra/zebra_rib.c13
-rw-r--r--zebra/zebra_routemap.c2
4 files changed, 83 insertions, 15 deletions
diff --git a/lib/nexthop.h b/lib/nexthop.h
index b3a128a2a8..b375c55b95 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -68,6 +68,7 @@ struct nexthop
/* Nexthop address */
union g_addr gate;
union g_addr src;
+ union g_addr rmap_src; /* Src is set via routemap */
/* Nexthops obtained by recursive resolution.
*
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index ea2d42ab3b..7c6b3782a5 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1466,7 +1466,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;
@@ -1475,7 +1476,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);
@@ -1508,7 +1513,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);
@@ -1569,8 +1577,10 @@ _netlink_route_build_multipath(
&nexthop->gate.ipv4, bytelen);
rtnh->rtnh_len += sizeof (struct rtattr) + 4;
- 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): "
@@ -1601,8 +1611,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);
@@ -1667,6 +1681,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
int nexthop_num;
int discard;
const char *routedesc;
+ int setsrc = 0;
+ union g_addr src;
struct
{
@@ -1754,7 +1770,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))
@@ -1766,7 +1798,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
_netlink_route_debug(cmd, p, nexthop, routedesc, family);
_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);
@@ -1775,13 +1807,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);
@@ -1794,7 +1828,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))
@@ -1807,15 +1857,21 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
_netlink_route_debug(cmd, p, nexthop,
routedesc, family);
_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),
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index a9f31b1a06..cd9f7005cc 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1184,6 +1184,9 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
if (!family)
family = info->afi;
+ memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr));
+ /* It'll get set if required inside */
+
ret = zebra_route_map_check(family, rib->type, &rn->p, nexthop);
if (ret == RMAP_DENYMATCH)
{
@@ -1195,6 +1198,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
}
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
}
+
return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
}
@@ -1211,6 +1215,7 @@ static int
nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
{
struct nexthop *nexthop;
+ union g_addr prev_src;
unsigned int prev_active, prev_index, new_active, old_num_nh;
old_num_nh = rib->nexthop_active_num;
@@ -1220,12 +1225,18 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
{
+ /* No protocol daemon provides src and so we're skipping tracking it */
+ prev_src = nexthop->rmap_src;
prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
prev_index = nexthop->ifindex;
if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
rib->nexthop_active_num++;
+ /* Don't allow src setting on IPv6 addr for now */
if (prev_active != new_active ||
- prev_index != nexthop->ifindex)
+ prev_index != nexthop->ifindex ||
+ ((nexthop->type >= NEXTHOP_TYPE_IFINDEX &&
+ nexthop->type < NEXTHOP_TYPE_IPV6) &&
+ prev_src.ipv4.s_addr != nexthop->rmap_src.ipv4.s_addr))
{
SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 3668448f73..ae30b6971e 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -1301,7 +1301,7 @@ route_set_src (void *rule, struct prefix *prefix,
if (type == RMAP_ZEBRA)
{
nh_data = (struct nh_rmap_obj *)object;
- nh_data->nexthop->src = *(union g_addr *)rule;
+ nh_data->nexthop->rmap_src = *(union g_addr *)rule;
}
return RMAP_OKAY;
}