mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 09:00:55 +00:00
MPLS: Install labeled static routes
This patch installs labeled static routes in the FIB. The routes are installed using the RTA_ENCAP (and RTA_ENCAP_TYPE) nested attributes. Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com> Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com> Ticket: CM-6040 Reviewed By: CCR-3091 Testing Done: Tested in SE-1, brief manual testing now
This commit is contained in:
parent
a22f3f5dad
commit
c0f4be83a1
@ -129,6 +129,9 @@ copy_nexthops (struct nexthop **tnh, struct nexthop *nh)
|
||||
nexthop->ifindex = nh->ifindex;
|
||||
memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr));
|
||||
memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr));
|
||||
if (nh->nh_label)
|
||||
nexthop_add_labels (nexthop, nh->nh_label->num_labels,
|
||||
&nh->nh_label->label[0]);
|
||||
nexthop_add(tnh, nexthop);
|
||||
|
||||
if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE))
|
||||
|
@ -77,12 +77,28 @@ static const struct message nlmsg_str[] = {
|
||||
#endif
|
||||
|
||||
#ifndef RTA_VIA
|
||||
#define RTA_VIA 16
|
||||
#define RTA_VIA 18
|
||||
#endif
|
||||
|
||||
#ifndef RTA_NEWDST
|
||||
#define RTA_NEWDST 19
|
||||
#endif
|
||||
|
||||
#ifndef RTA_ENCAP_TYPE
|
||||
#define RTA_ENCAP_TYPE 21
|
||||
#endif
|
||||
|
||||
#ifndef RTA_ENCAP
|
||||
#define RTA_ENCAP 22
|
||||
#endif
|
||||
|
||||
#ifndef LWTUNNEL_ENCAP_MPLS
|
||||
#define LWTUNNEL_ENCAP_MPLS 1
|
||||
#endif
|
||||
|
||||
#ifndef MPLS_IPTUNNEL_DST
|
||||
#define MPLS_IPTUNNEL_DST 1
|
||||
#endif
|
||||
/* End of temporary definitions */
|
||||
|
||||
struct gw_family_t
|
||||
@ -1720,6 +1736,39 @@ addattr32 (struct nlmsghdr *n, unsigned int maxlen, int type, int data)
|
||||
return addattr_l(n, maxlen, type, &data, sizeof(u_int32_t));
|
||||
}
|
||||
|
||||
/* Some more utility functions from iproute2 */
|
||||
static struct rtattr *
|
||||
addattr_nest(struct nlmsghdr *n, int maxlen, int type)
|
||||
{
|
||||
struct rtattr *nest = NLMSG_TAIL(n);
|
||||
|
||||
addattr_l(n, maxlen, type, NULL, 0);
|
||||
return nest;
|
||||
}
|
||||
|
||||
static int
|
||||
addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest)
|
||||
{
|
||||
nest->rta_len = NLMSG_TAIL(n) - nest;
|
||||
return n->nlmsg_len;
|
||||
}
|
||||
|
||||
static struct rtattr *
|
||||
rta_nest(struct rtattr *rta, int maxlen, int type)
|
||||
{
|
||||
struct rtattr *nest = RTA_TAIL(rta);
|
||||
|
||||
rta_addattr_l(rta, maxlen, type, NULL, 0);
|
||||
return nest;
|
||||
}
|
||||
|
||||
static int
|
||||
rta_nest_end(struct rtattr *rta, struct rtattr *nest)
|
||||
{
|
||||
nest->rta_len = RTA_TAIL(rta) - nest;
|
||||
return rta->rta_len;
|
||||
}
|
||||
|
||||
static int
|
||||
netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h,
|
||||
ns_id_t ns_id)
|
||||
@ -1865,7 +1914,8 @@ _netlink_route_build_singlepath(
|
||||
size_t req_size,
|
||||
int cmd)
|
||||
{
|
||||
mpls_lse_t out_lse;
|
||||
struct nexthop_label *nh_label;
|
||||
mpls_lse_t out_lse[MPLS_MAX_LABELS];
|
||||
char label_buf[100];
|
||||
|
||||
if (rtmsg->rtm_family == AF_INET &&
|
||||
@ -1895,16 +1945,55 @@ _netlink_route_build_singlepath(
|
||||
}
|
||||
|
||||
label_buf[0] = '\0';
|
||||
/* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
|
||||
* (in the case of LER)
|
||||
*/
|
||||
nh_label = nexthop->nh_label;
|
||||
if (rtmsg->rtm_family == AF_MPLS)
|
||||
{
|
||||
assert (nexthop->nh_label);
|
||||
assert (nh_label);
|
||||
assert (nh_label->num_labels == 1);
|
||||
}
|
||||
|
||||
/* Fill out label, if present. */
|
||||
if (nexthop->nh_label->label[0] != MPLS_IMP_NULL_LABEL)
|
||||
if (nh_label && nh_label->num_labels)
|
||||
{
|
||||
int i, num_labels = 0;
|
||||
u_int32_t bos;
|
||||
char label_buf1[20];
|
||||
|
||||
for (i = 0; i < nh_label->num_labels; i++)
|
||||
{
|
||||
out_lse = mpls_lse_encode (nexthop->nh_label->label[0], 0, 0, 1);
|
||||
addattr_l (nlmsg, req_size, RTA_NEWDST, &out_lse, sizeof(mpls_lse_t));
|
||||
sprintf (label_buf, "label %d", nexthop->nh_label->label[0]);
|
||||
if (nh_label->label[i] != MPLS_IMP_NULL_LABEL)
|
||||
{
|
||||
bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0);
|
||||
out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos);
|
||||
if (!num_labels)
|
||||
sprintf (label_buf, "label %d", nh_label->label[i]);
|
||||
else
|
||||
{
|
||||
sprintf (label_buf1, "/%d", nh_label->label[i]);
|
||||
strcat (label_buf, label_buf1);
|
||||
}
|
||||
num_labels++;
|
||||
}
|
||||
}
|
||||
if (num_labels)
|
||||
{
|
||||
if (rtmsg->rtm_family == AF_MPLS)
|
||||
addattr_l (nlmsg, req_size, RTA_NEWDST,
|
||||
&out_lse, num_labels * sizeof(mpls_lse_t));
|
||||
else
|
||||
{
|
||||
struct rtattr *nest;
|
||||
u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
|
||||
|
||||
addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE,
|
||||
&encap, sizeof (u_int16_t));
|
||||
nest = addattr_nest(nlmsg, req_size, RTA_ENCAP);
|
||||
addattr_l (nlmsg, req_size, MPLS_IPTUNNEL_DST,
|
||||
&out_lse, num_labels * sizeof(mpls_lse_t));
|
||||
addattr_nest_end(nlmsg, nest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2023,7 +2112,8 @@ _netlink_route_build_multipath(
|
||||
struct rtmsg *rtmsg,
|
||||
union g_addr **src)
|
||||
{
|
||||
mpls_lse_t out_lse;
|
||||
struct nexthop_label *nh_label;
|
||||
mpls_lse_t out_lse[MPLS_MAX_LABELS];
|
||||
char label_buf[100];
|
||||
|
||||
rtnh->rtnh_len = sizeof (*rtnh);
|
||||
@ -2059,18 +2149,60 @@ _netlink_route_build_multipath(
|
||||
}
|
||||
|
||||
label_buf[0] = '\0';
|
||||
/* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
|
||||
* (in the case of LER)
|
||||
*/
|
||||
nh_label = nexthop->nh_label;
|
||||
if (rtmsg->rtm_family == AF_MPLS)
|
||||
{
|
||||
assert (nexthop->nh_label);
|
||||
assert (nh_label);
|
||||
assert (nh_label->num_labels == 1);
|
||||
}
|
||||
|
||||
/* Fill out label, if present. */
|
||||
if (nexthop->nh_label->label[0] != MPLS_IMP_NULL_LABEL)
|
||||
if (nh_label && nh_label->num_labels)
|
||||
{
|
||||
int i, num_labels = 0;
|
||||
u_int32_t bos;
|
||||
char label_buf1[20];
|
||||
|
||||
for (i = 0; i < nh_label->num_labels; i++)
|
||||
{
|
||||
out_lse = mpls_lse_encode (nexthop->nh_label->label[0], 0, 0, 1);
|
||||
rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_NEWDST,
|
||||
&out_lse, sizeof(mpls_lse_t));
|
||||
rtnh->rtnh_len += RTA_LENGTH (sizeof(mpls_lse_t));
|
||||
sprintf (label_buf, "label %d", nexthop->nh_label->label[0]);
|
||||
if (nh_label->label[i] != MPLS_IMP_NULL_LABEL)
|
||||
{
|
||||
bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0);
|
||||
out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos);
|
||||
if (!num_labels)
|
||||
sprintf (label_buf, "label %d", nh_label->label[i]);
|
||||
else
|
||||
{
|
||||
sprintf (label_buf1, "/%d", nh_label->label[i]);
|
||||
strcat (label_buf, label_buf1);
|
||||
}
|
||||
num_labels++;
|
||||
}
|
||||
}
|
||||
if (num_labels)
|
||||
{
|
||||
if (rtmsg->rtm_family == AF_MPLS)
|
||||
{
|
||||
rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_NEWDST,
|
||||
&out_lse, num_labels * sizeof(mpls_lse_t));
|
||||
rtnh->rtnh_len += RTA_LENGTH (num_labels * sizeof(mpls_lse_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
struct rtattr *nest;
|
||||
u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
|
||||
int len = rta->rta_len;
|
||||
|
||||
rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_ENCAP_TYPE,
|
||||
&encap, sizeof (u_int16_t));
|
||||
nest = rta_nest(rta, NL_PKT_BUF_SIZE, RTA_ENCAP);
|
||||
rta_addattr_l (rta, NL_PKT_BUF_SIZE, MPLS_IPTUNNEL_DST,
|
||||
&out_lse, num_labels * sizeof(mpls_lse_t));
|
||||
rta_nest_end(rta, nest);
|
||||
rtnh->rtnh_len += rta->rta_len - len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,9 @@ rib_copy_nexthops (struct rib *rib, struct nexthop *nh)
|
||||
nexthop->ifindex = nh->ifindex;
|
||||
memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr));
|
||||
memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr));
|
||||
if (nh->nh_label)
|
||||
nexthop_add_labels (nexthop, nh->nh_label->num_labels,
|
||||
&nh->nh_label->label[0]);
|
||||
rib_nexthop_add(rib, nexthop);
|
||||
if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE))
|
||||
copy_nexthops(&nexthop->resolved, nh->resolved);
|
||||
|
@ -42,6 +42,7 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ro
|
||||
struct route_node *rn;
|
||||
struct route_table *table;
|
||||
struct prefix nh_p;
|
||||
struct nexthop *nexthop = NULL;
|
||||
|
||||
/* Lookup table. */
|
||||
table = zebra_vrf_table (afi, safi, si->vrf_id);
|
||||
@ -71,29 +72,34 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ro
|
||||
switch (si->type)
|
||||
{
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
|
||||
nexthop = rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
|
||||
nh_p.family = AF_INET;
|
||||
nh_p.prefixlen = IPV4_MAX_BITLEN;
|
||||
nh_p.u.prefix4 = si->addr.ipv4;
|
||||
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
||||
break;
|
||||
case STATIC_IFINDEX:
|
||||
rib_nexthop_ifindex_add (rib, si->ifindex);
|
||||
nexthop = rib_nexthop_ifindex_add (rib, si->ifindex);
|
||||
break;
|
||||
case STATIC_IPV4_BLACKHOLE:
|
||||
rib_nexthop_blackhole_add (rib);
|
||||
nexthop = rib_nexthop_blackhole_add (rib);
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
|
||||
nexthop = rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
|
||||
nh_p.family = AF_INET6;
|
||||
nh_p.prefixlen = IPV6_MAX_BITLEN;
|
||||
nh_p.u.prefix6 = si->addr.ipv6;
|
||||
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY_IFINDEX:
|
||||
rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex);
|
||||
nexthop = rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6,
|
||||
si->ifindex);
|
||||
break;
|
||||
}
|
||||
/* Update label(s), if present. */
|
||||
if (si->snh_label.num_labels)
|
||||
nexthop_add_labels (nexthop, si->snh_label.num_labels,
|
||||
&si->snh_label.label[0]);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
{
|
||||
@ -130,29 +136,34 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ro
|
||||
switch (si->type)
|
||||
{
|
||||
case STATIC_IPV4_GATEWAY:
|
||||
rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
|
||||
nexthop = rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
|
||||
nh_p.family = AF_INET;
|
||||
nh_p.prefixlen = IPV4_MAX_BITLEN;
|
||||
nh_p.u.prefix4 = si->addr.ipv4;
|
||||
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
||||
break;
|
||||
case STATIC_IFINDEX:
|
||||
rib_nexthop_ifindex_add (rib, si->ifindex);
|
||||
nexthop = rib_nexthop_ifindex_add (rib, si->ifindex);
|
||||
break;
|
||||
case STATIC_IPV4_BLACKHOLE:
|
||||
rib_nexthop_blackhole_add (rib);
|
||||
nexthop = rib_nexthop_blackhole_add (rib);
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
|
||||
nexthop = rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
|
||||
nh_p.family = AF_INET6;
|
||||
nh_p.prefixlen = IPV6_MAX_BITLEN;
|
||||
nh_p.u.prefix6 = si->addr.ipv6;
|
||||
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY_IFINDEX:
|
||||
rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex);
|
||||
nexthop = rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6,
|
||||
si->ifindex);
|
||||
break;
|
||||
}
|
||||
/* Update label(s), if present. */
|
||||
if (si->snh_label.num_labels)
|
||||
nexthop_add_labels (nexthop, si->snh_label.num_labels,
|
||||
&si->snh_label.label[0]);
|
||||
|
||||
/* Save the flags of this static routes (reject, blackhole) */
|
||||
rib->flags = si->flags;
|
||||
@ -181,30 +192,59 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ro
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
static_nexthop_label_same (struct nexthop *nexthop,
|
||||
struct static_nh_label *snh_label)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((snh_label->num_labels == 0 && nexthop->nh_label) ||
|
||||
(snh_label->num_labels != 0 && !nexthop->nh_label))
|
||||
return 0;
|
||||
|
||||
if (snh_label->num_labels != 0)
|
||||
if (snh_label->num_labels != nexthop->nh_label->num_labels)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < snh_label->num_labels; i++)
|
||||
if (snh_label->label[i] != nexthop->nh_label->label[i])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
static_nexthop_same (struct nexthop *nexthop, struct static_route *si)
|
||||
{
|
||||
if (nexthop->type == NEXTHOP_TYPE_IPV4
|
||||
&& si->type == STATIC_IPV4_GATEWAY
|
||||
&& IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
|
||||
return 1;
|
||||
if (nexthop->type == NEXTHOP_TYPE_IFINDEX
|
||||
&& si->type == STATIC_IFINDEX
|
||||
&& nexthop->ifindex == si->ifindex)
|
||||
return 1;
|
||||
int gw_match = 0;
|
||||
|
||||
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
|
||||
&& si->type == STATIC_IPV4_BLACKHOLE)
|
||||
return 1;
|
||||
if (nexthop->type == NEXTHOP_TYPE_IPV6
|
||||
|
||||
if (nexthop->type == NEXTHOP_TYPE_IPV4
|
||||
&& si->type == STATIC_IPV4_GATEWAY
|
||||
&& IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
|
||||
gw_match = 1;
|
||||
else if (nexthop->type == NEXTHOP_TYPE_IFINDEX
|
||||
&& si->type == STATIC_IFINDEX
|
||||
&& nexthop->ifindex == si->ifindex)
|
||||
gw_match = 1;
|
||||
else if (nexthop->type == NEXTHOP_TYPE_IPV6
|
||||
&& si->type == STATIC_IPV6_GATEWAY
|
||||
&& IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
|
||||
return 1;
|
||||
if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
|
||||
gw_match = 1;
|
||||
else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
|
||||
&& si->type == STATIC_IPV6_GATEWAY_IFINDEX
|
||||
&& IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
|
||||
&& nexthop->ifindex == si->ifindex)
|
||||
return 1;
|
||||
return 0;
|
||||
gw_match = 1;
|
||||
|
||||
if (!gw_match)
|
||||
return 0;
|
||||
|
||||
/* Check match on label(s), if any */
|
||||
return static_nexthop_label_same (nexthop, &si->snh_label);
|
||||
}
|
||||
|
||||
/* Uninstall static route from RIB. */
|
||||
|
@ -2318,6 +2318,15 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Label information */
|
||||
if (nexthop->nh_label && nexthop->nh_label->num_labels)
|
||||
{
|
||||
vty_out (vty, " label %s",
|
||||
mpls_label2str (nexthop->nh_label->num_labels,
|
||||
nexthop->nh_label->label, buf, BUFSIZ));
|
||||
}
|
||||
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
}
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
@ -2558,6 +2567,14 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Label information */
|
||||
if (nexthop->nh_label && nexthop->nh_label->num_labels)
|
||||
{
|
||||
vty_out (vty, " label %s",
|
||||
mpls_label2str (nexthop->nh_label->num_labels,
|
||||
nexthop->nh_label->label, buf, BUFSIZ));
|
||||
}
|
||||
|
||||
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
|
||||
vty_out (vty, ", bh");
|
||||
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
|
||||
|
Loading…
Reference in New Issue
Block a user