mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 23:42:15 +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 */
|
/* Nexthop address */
|
||||||
union g_addr gate;
|
union g_addr gate;
|
||||||
union g_addr src;
|
union g_addr src;
|
||||||
|
union g_addr rmap_src; /* Src is set via routemap */
|
||||||
|
|
||||||
/* Nexthops obtained by recursive resolution.
|
/* Nexthops obtained by recursive resolution.
|
||||||
*
|
*
|
||||||
|
@ -1466,7 +1466,8 @@ _netlink_route_build_singlepath(
|
|||||||
struct nexthop *nexthop,
|
struct nexthop *nexthop,
|
||||||
struct nlmsghdr *nlmsg,
|
struct nlmsghdr *nlmsg,
|
||||||
struct rtmsg *rtmsg,
|
struct rtmsg *rtmsg,
|
||||||
size_t req_size)
|
size_t req_size,
|
||||||
|
int cmd)
|
||||||
{
|
{
|
||||||
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
|
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
|
||||||
rtmsg->rtm_flags |= RTNH_F_ONLINK;
|
rtmsg->rtm_flags |= RTNH_F_ONLINK;
|
||||||
@ -1475,7 +1476,11 @@ _netlink_route_build_singlepath(
|
|||||||
{
|
{
|
||||||
addattr_l (nlmsg, req_size, RTA_GATEWAY,
|
addattr_l (nlmsg, req_size, RTA_GATEWAY,
|
||||||
&nexthop->gate.ipv4, bytelen);
|
&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,
|
addattr_l (nlmsg, req_size, RTA_PREFSRC,
|
||||||
&nexthop->src.ipv4, bytelen);
|
&nexthop->src.ipv4, bytelen);
|
||||||
|
|
||||||
@ -1508,7 +1513,10 @@ _netlink_route_build_singlepath(
|
|||||||
{
|
{
|
||||||
addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
|
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,
|
addattr_l (nlmsg, req_size, RTA_PREFSRC,
|
||||||
&nexthop->src.ipv4, bytelen);
|
&nexthop->src.ipv4, bytelen);
|
||||||
|
|
||||||
@ -1569,8 +1577,10 @@ _netlink_route_build_multipath(
|
|||||||
&nexthop->gate.ipv4, bytelen);
|
&nexthop->gate.ipv4, bytelen);
|
||||||
rtnh->rtnh_len += sizeof (struct rtattr) + 4;
|
rtnh->rtnh_len += sizeof (struct rtattr) + 4;
|
||||||
|
|
||||||
if (nexthop->src.ipv4.s_addr)
|
if (nexthop->rmap_src.ipv4.s_addr)
|
||||||
*src = &nexthop->src;
|
*src = &nexthop->rmap_src;
|
||||||
|
else if (nexthop->src.ipv4.s_addr)
|
||||||
|
*src = &nexthop->src;
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||||
zlog_debug("netlink_route_multipath() (%s): "
|
zlog_debug("netlink_route_multipath() (%s): "
|
||||||
@ -1601,8 +1611,12 @@ _netlink_route_build_multipath(
|
|||||||
|| nexthop->type == NEXTHOP_TYPE_IFNAME)
|
|| nexthop->type == NEXTHOP_TYPE_IFNAME)
|
||||||
{
|
{
|
||||||
rtnh->rtnh_ifindex = nexthop->ifindex;
|
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;
|
*src = &nexthop->src;
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||||
zlog_debug("netlink_route_multipath() (%s): "
|
zlog_debug("netlink_route_multipath() (%s): "
|
||||||
"nexthop via if %u", routedesc, nexthop->ifindex);
|
"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 nexthop_num;
|
||||||
int discard;
|
int discard;
|
||||||
const char *routedesc;
|
const char *routedesc;
|
||||||
|
int setsrc = 0;
|
||||||
|
union g_addr src;
|
||||||
|
|
||||||
struct
|
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))
|
for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
|
||||||
{
|
{
|
||||||
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
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
|
if ((cmd == RTM_NEWROUTE
|
||||||
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
&& 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_debug(cmd, p, nexthop, routedesc, family);
|
||||||
_netlink_route_build_singlepath(routedesc, bytelen,
|
_netlink_route_build_singlepath(routedesc, bytelen,
|
||||||
nexthop, &req.n, &req.r,
|
nexthop, &req.n, &req.r,
|
||||||
sizeof req);
|
sizeof req, cmd);
|
||||||
|
|
||||||
if (cmd == RTM_NEWROUTE)
|
if (cmd == RTM_NEWROUTE)
|
||||||
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
|
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
|
||||||
@ -1775,13 +1807,15 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (setsrc && (cmd == RTM_NEWROUTE))
|
||||||
|
addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char buf[NL_PKT_BUF_SIZE];
|
char buf[NL_PKT_BUF_SIZE];
|
||||||
struct rtattr *rta = (void *) buf;
|
struct rtattr *rta = (void *) buf;
|
||||||
struct rtnexthop *rtnh;
|
struct rtnexthop *rtnh;
|
||||||
union g_addr *src = NULL;
|
union g_addr *src1 = NULL;
|
||||||
|
|
||||||
rta->rta_type = RTA_MULTIPATH;
|
rta->rta_type = RTA_MULTIPATH;
|
||||||
rta->rta_len = RTA_LENGTH (0);
|
rta->rta_len = RTA_LENGTH (0);
|
||||||
@ -1794,7 +1828,23 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
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
|
if ((cmd == RTM_NEWROUTE
|
||||||
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
&& 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,
|
_netlink_route_debug(cmd, p, nexthop,
|
||||||
routedesc, family);
|
routedesc, family);
|
||||||
_netlink_route_build_multipath(routedesc, bytelen,
|
_netlink_route_build_multipath(routedesc, bytelen,
|
||||||
nexthop, rta, rtnh, &src);
|
nexthop, rta, rtnh, &src1);
|
||||||
rtnh = RTNH_NEXT (rtnh);
|
rtnh = RTNH_NEXT (rtnh);
|
||||||
|
|
||||||
if (cmd == RTM_NEWROUTE)
|
if (cmd == RTM_NEWROUTE)
|
||||||
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
|
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
|
||||||
|
|
||||||
|
if (!setsrc && src1)
|
||||||
|
{
|
||||||
|
src.ipv4 = src1->ipv4;
|
||||||
|
setsrc = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (src)
|
if (setsrc && (cmd == RTM_NEWROUTE))
|
||||||
addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);
|
addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
|
||||||
|
|
||||||
if (rta->rta_len > RTA_LENGTH (0))
|
if (rta->rta_len > RTA_LENGTH (0))
|
||||||
addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
|
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)
|
if (!family)
|
||||||
family = info->afi;
|
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);
|
ret = zebra_route_map_check(family, rib->type, &rn->p, nexthop);
|
||||||
if (ret == RMAP_DENYMATCH)
|
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);
|
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CHECK_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)
|
nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
|
||||||
{
|
{
|
||||||
struct nexthop *nexthop;
|
struct nexthop *nexthop;
|
||||||
|
union g_addr prev_src;
|
||||||
unsigned int prev_active, prev_index, new_active, old_num_nh;
|
unsigned int prev_active, prev_index, new_active, old_num_nh;
|
||||||
|
|
||||||
old_num_nh = rib->nexthop_active_num;
|
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)
|
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_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||||
prev_index = nexthop->ifindex;
|
prev_index = nexthop->ifindex;
|
||||||
if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
|
if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
|
||||||
rib->nexthop_active_num++;
|
rib->nexthop_active_num++;
|
||||||
|
/* Don't allow src setting on IPv6 addr for now */
|
||||||
if (prev_active != new_active ||
|
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->flags, ZEBRA_FLAG_CHANGED);
|
||||||
SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_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)
|
if (type == RMAP_ZEBRA)
|
||||||
{
|
{
|
||||||
nh_data = (struct nh_rmap_obj *)object;
|
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;
|
return RMAP_OKAY;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user