mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-04 08:21:42 +00:00
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>
This commit is contained in:
parent
b5d58c32bb
commit
c52ef59fed
@ -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.
|
||||
*
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user