mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-29 10:11:52 +00:00
zebra: labeled unicast handling
Support install of labeled-unicast routes by a client. This would be BGP, in order to install routes corresponding to AFI/SAFI 1/4 (IPv4) or 2/4 (IPv6). Convert labeled-unicast routes into label forwarding entries (i.e., transit LSPs) when there is a static label binding. Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
This commit is contained in:
parent
cceb79ac9b
commit
a64448baa6
@ -85,7 +85,8 @@ enum lsp_types_t
|
||||
{
|
||||
ZEBRA_LSP_NONE = 0, /* No LSP. */
|
||||
ZEBRA_LSP_STATIC = 1, /* Static LSP. */
|
||||
ZEBRA_LSP_LDP = 2 /* LDP LSP. */
|
||||
ZEBRA_LSP_LDP = 2, /* LDP LSP. */
|
||||
ZEBRA_LSP_BGP = 3 /* BGP LSP. */
|
||||
};
|
||||
|
||||
/* Functions for basic label operations. */
|
||||
|
@ -92,6 +92,28 @@ nexthop_type_to_str (enum nexthop_types_t nh_type)
|
||||
return desc[nh_type];
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the labels match for the 2 nexthops specified.
|
||||
*/
|
||||
int
|
||||
nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2)
|
||||
{
|
||||
struct nexthop_label *nhl1, *nhl2;
|
||||
|
||||
nhl1 = nh1->nh_label;
|
||||
nhl2 = nh2->nh_label;
|
||||
if ((nhl1 && !nhl2) || (!nhl1 && nhl2))
|
||||
return 0;
|
||||
|
||||
if (nhl1->num_labels != nhl2->num_labels)
|
||||
return 0;
|
||||
|
||||
if (memcmp (nhl1->label, nhl2->label, nhl1->num_labels))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct nexthop *
|
||||
nexthop_new (void)
|
||||
{
|
||||
|
@ -117,6 +117,7 @@ void nexthop_del_labels (struct nexthop *);
|
||||
|
||||
extern const char *nexthop_type_to_str (enum nexthop_types_t nh_type);
|
||||
extern int nexthop_same_no_recurse (struct nexthop *next1, struct nexthop *next2);
|
||||
extern int nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2);
|
||||
|
||||
extern const char * nexthop2str (struct nexthop *nexthop, char *str, int size);
|
||||
#endif /*_LIB_NEXTHOP_H */
|
||||
|
@ -733,6 +733,18 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
|
||||
s = zclient->obuf;
|
||||
stream_reset (s);
|
||||
|
||||
/* Some checks for labeled-unicast. The current expectation is that each
|
||||
* nexthop is accompanied by a label in the case of labeled-unicast.
|
||||
*/
|
||||
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) &&
|
||||
CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
|
||||
{
|
||||
/* We expect prefixes installed with labels and the number to match
|
||||
* the number of nexthops.
|
||||
*/
|
||||
assert (api->label_num == api->nexthop_num);
|
||||
}
|
||||
|
||||
zclient_create_header (s, cmd, api->vrf_id);
|
||||
|
||||
/* Put type and nexthop. */
|
||||
@ -749,7 +761,7 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
|
||||
|
||||
/* Nexthop, ifindex, distance and metric information. */
|
||||
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
|
||||
{
|
||||
{
|
||||
/* traditional 32-bit data units */
|
||||
if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE))
|
||||
{
|
||||
@ -765,6 +777,9 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
|
||||
{
|
||||
stream_putc (s, NEXTHOP_TYPE_IPV4);
|
||||
stream_put_in_addr (s, api->nexthop[i]);
|
||||
/* For labeled-unicast, each nexthop is followed by label. */
|
||||
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL))
|
||||
stream_putl (s, api->label[i]);
|
||||
}
|
||||
for (i = 0; i < api->ifindex_num; i++)
|
||||
{
|
||||
@ -800,6 +815,18 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient,
|
||||
s = zclient->obuf;
|
||||
stream_reset (s);
|
||||
|
||||
/* Some checks for labeled-unicast. The current expectation is that each
|
||||
* nexthop is accompanied by a label in the case of labeled-unicast.
|
||||
*/
|
||||
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) &&
|
||||
CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
|
||||
{
|
||||
/* We expect prefixes installed with labels and the number to match
|
||||
* the number of nexthops.
|
||||
*/
|
||||
assert (api->label_num == api->nexthop_num);
|
||||
}
|
||||
|
||||
zclient_create_header (s, cmd, api->vrf_id);
|
||||
|
||||
/* Put type and nexthop. */
|
||||
@ -831,6 +858,9 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient,
|
||||
{
|
||||
stream_putc (s, NEXTHOP_TYPE_IPV6);
|
||||
stream_write (s, (u_char *)api->nexthop[i], 16);
|
||||
/* For labeled-unicast, each nexthop is followed by label. */
|
||||
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL))
|
||||
stream_putl (s, api->label[i]);
|
||||
}
|
||||
for (i = 0; i < api->ifindex_num; i++)
|
||||
{
|
||||
@ -869,6 +899,18 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
|
||||
s = zclient->obuf;
|
||||
stream_reset (s);
|
||||
|
||||
/* Some checks for labeled-unicast. The current expectation is that each
|
||||
* nexthop is accompanied by a label in the case of labeled-unicast.
|
||||
*/
|
||||
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) &&
|
||||
CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
|
||||
{
|
||||
/* We expect prefixes installed with labels and the number to match
|
||||
* the number of nexthops.
|
||||
*/
|
||||
assert (api->label_num == api->nexthop_num);
|
||||
}
|
||||
|
||||
zclient_create_header (s, cmd, api->vrf_id);
|
||||
|
||||
/* Put type and nexthop. */
|
||||
@ -907,6 +949,9 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
|
||||
{
|
||||
stream_putc (s, NEXTHOP_TYPE_IPV6);
|
||||
stream_write (s, (u_char *)api->nexthop[i], 16);
|
||||
/* For labeled-unicast, each nexthop is followed by label. */
|
||||
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL))
|
||||
stream_putl (s, api->label[i]);
|
||||
}
|
||||
for (i = 0; i < api->ifindex_num; i++)
|
||||
{
|
||||
|
@ -178,6 +178,7 @@ struct zclient
|
||||
#define ZAPI_MESSAGE_TAG 0x10
|
||||
#define ZAPI_MESSAGE_MTU 0x20
|
||||
#define ZAPI_MESSAGE_SRCPFX 0x40
|
||||
#define ZAPI_MESSAGE_LABEL 0x80
|
||||
|
||||
/* Zserv protocol message header */
|
||||
struct zserv_header
|
||||
@ -210,6 +211,9 @@ struct zapi_ipv4
|
||||
u_char ifindex_num;
|
||||
ifindex_t *ifindex;
|
||||
|
||||
u_char label_num;
|
||||
unsigned int *label;
|
||||
|
||||
u_char distance;
|
||||
|
||||
u_int32_t metric;
|
||||
@ -301,6 +305,9 @@ struct zapi_ipv6
|
||||
u_char ifindex_num;
|
||||
ifindex_t *ifindex;
|
||||
|
||||
u_char label_num;
|
||||
unsigned int *label;
|
||||
|
||||
u_char distance;
|
||||
|
||||
u_int32_t metric;
|
||||
|
@ -413,11 +413,13 @@ typedef enum {
|
||||
#define SAFI_ENCAP 5
|
||||
#define SAFI_RESERVED_5 5
|
||||
#define SAFI_EVPN 6
|
||||
#define SAFI_MAX 7
|
||||
#define SAFI_LABELED_UNICAST 7
|
||||
#define SAFI_MAX 8
|
||||
|
||||
#define IANA_SAFI_RESERVED 0
|
||||
#define IANA_SAFI_UNICAST 1
|
||||
#define IANA_SAFI_MULTICAST 2
|
||||
#define IANA_SAFI_LABELED_UNICAST 4
|
||||
#define IANA_SAFI_ENCAP 7
|
||||
#define IANA_SAFI_MPLS_VPN 128
|
||||
|
||||
|
@ -372,7 +372,7 @@ extern void rib_init (void);
|
||||
extern unsigned long rib_score_proto (u_char proto, u_short instance);
|
||||
extern void rib_queue_add (struct route_node *rn);
|
||||
extern void meta_queue_free (struct meta_queue *mq);
|
||||
|
||||
extern int zebra_rib_labeled_unicast (struct rib *rib);
|
||||
extern struct route_table *rib_table_ipv6;
|
||||
|
||||
extern void rib_unlink (struct route_node *, struct rib *);
|
||||
|
@ -60,6 +60,13 @@ extern struct zebra_t zebrad;
|
||||
|
||||
/* static function declarations */
|
||||
|
||||
static int
|
||||
lsp_install (struct zebra_vrf *zvrf, mpls_label_t label,
|
||||
struct route_node *rn, struct rib *rib);
|
||||
static int
|
||||
lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label);
|
||||
static int
|
||||
fec_change_update_lsp (struct zebra_vrf *zvrf, zebra_fec_t *fec, mpls_label_t old_label);
|
||||
static int
|
||||
fec_send (zebra_fec_t *fec, struct zserv *client);
|
||||
static void
|
||||
@ -69,7 +76,7 @@ fec_print (zebra_fec_t *fec, struct vty *vty);
|
||||
static zebra_fec_t *
|
||||
fec_find (struct route_table *table, struct prefix *p);
|
||||
static zebra_fec_t *
|
||||
fec_add (struct route_table *table, struct prefix *p, u_int32_t label,
|
||||
fec_add (struct route_table *table, struct prefix *p, mpls_label_t label,
|
||||
u_int32_t flags);
|
||||
static int
|
||||
fec_del (zebra_fec_t *fec);
|
||||
@ -106,17 +113,19 @@ static char *
|
||||
nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size);
|
||||
static int
|
||||
nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex);
|
||||
union g_addr *gate, ifindex_t ifindex);
|
||||
static zebra_nhlfe_t *
|
||||
nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
|
||||
enum nexthop_types_t gtype, union g_addr *gate,
|
||||
char *ifname, ifindex_t ifindex);
|
||||
ifindex_t ifindex);
|
||||
static zebra_nhlfe_t *
|
||||
nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
|
||||
enum nexthop_types_t gtype, union g_addr *gate,
|
||||
char *ifname, ifindex_t ifindex, mpls_label_t out_label);
|
||||
ifindex_t ifindex, mpls_label_t out_label);
|
||||
static int
|
||||
nhlfe_del (zebra_nhlfe_t *snhlfe);
|
||||
static void
|
||||
nhlfe_out_label_update (zebra_nhlfe_t *nhlfe, struct nexthop_label *nh_label);
|
||||
static int
|
||||
mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp,
|
||||
enum lsp_types_t type);
|
||||
@ -130,14 +139,13 @@ static void *
|
||||
slsp_alloc (void *p);
|
||||
static int
|
||||
snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex);
|
||||
union g_addr *gate, ifindex_t ifindex);
|
||||
static zebra_snhlfe_t *
|
||||
snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex);
|
||||
union g_addr *gate, ifindex_t ifindex);
|
||||
static zebra_snhlfe_t *
|
||||
snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex,
|
||||
mpls_label_t out_label);
|
||||
union g_addr *gate, ifindex_t ifindex, mpls_label_t out_label);
|
||||
static int
|
||||
snhlfe_del (zebra_snhlfe_t *snhlfe);
|
||||
static int
|
||||
@ -152,6 +160,245 @@ mpls_processq_init (struct zebra_t *zebra);
|
||||
|
||||
/* Static functions */
|
||||
|
||||
/*
|
||||
* Install label forwarding entry based on labeled-route entry.
|
||||
*/
|
||||
static int
|
||||
lsp_install (struct zebra_vrf *zvrf, mpls_label_t label,
|
||||
struct route_node *rn, struct rib *rib)
|
||||
{
|
||||
struct hash *lsp_table;
|
||||
zebra_ile_t tmp_ile;
|
||||
zebra_lsp_t *lsp;
|
||||
zebra_nhlfe_t *nhlfe;
|
||||
struct nexthop *nexthop;
|
||||
enum lsp_types_t lsp_type;
|
||||
char buf[BUFSIZ];
|
||||
int added, changed;
|
||||
|
||||
/* Lookup table. */
|
||||
lsp_table = zvrf->lsp_table;
|
||||
if (!lsp_table)
|
||||
return -1;
|
||||
|
||||
/* See if route entry is selected; we really expect only 1 entry here. */
|
||||
if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
|
||||
return 0;
|
||||
|
||||
lsp_type = lsp_type_from_rib_type (rib->type);
|
||||
added = changed = 0;
|
||||
|
||||
/* Locate or allocate LSP entry. */
|
||||
tmp_ile.in_label = label;
|
||||
lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc);
|
||||
if (!lsp)
|
||||
return -1;
|
||||
|
||||
/* For each active nexthop, create NHLFE. Note that we deliberately skip
|
||||
* recursive nexthops right now, because intermediate hops won't understand
|
||||
* the label advertised by the recursive nexthop (plus we don't have the
|
||||
* logic yet to push multiple labels).
|
||||
*/
|
||||
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
|
||||
{
|
||||
/* Skip inactive and recursive entries. */
|
||||
if (!CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
||||
continue;
|
||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
||||
continue;
|
||||
|
||||
nhlfe = nhlfe_find (lsp, lsp_type, nexthop->type, &nexthop->gate,
|
||||
nexthop->ifindex);
|
||||
if (nhlfe)
|
||||
{
|
||||
/* Clear deleted flag (in case it was set) */
|
||||
UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
|
||||
if (nexthop_labels_match (nhlfe->nexthop, nexthop))
|
||||
/* No change */
|
||||
continue;
|
||||
|
||||
|
||||
if (IS_ZEBRA_DEBUG_MPLS)
|
||||
{
|
||||
nhlfe2str (nhlfe, buf, BUFSIZ);
|
||||
zlog_debug ("LSP in-label %u type %d nexthop %s "
|
||||
"out-label changed",
|
||||
lsp->ile.in_label, lsp_type, buf);
|
||||
}
|
||||
|
||||
/* Update out label, trigger processing. */
|
||||
nhlfe_out_label_update (nhlfe, nexthop->nh_label);
|
||||
SET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
|
||||
changed++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add LSP entry to this nexthop */
|
||||
nhlfe = nhlfe_add (lsp, lsp_type, nexthop->type,
|
||||
&nexthop->gate, nexthop->ifindex,
|
||||
nexthop->nh_label->label[0]);
|
||||
if (!nhlfe)
|
||||
return -1;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_MPLS)
|
||||
{
|
||||
nhlfe2str (nhlfe, buf, BUFSIZ);
|
||||
zlog_debug ("Add LSP in-label %u type %d nexthop %s "
|
||||
"out-label %u",
|
||||
lsp->ile.in_label, lsp_type, buf,
|
||||
nexthop->nh_label->label[0]);
|
||||
}
|
||||
|
||||
lsp->addr_family = NHLFE_FAMILY (nhlfe);
|
||||
|
||||
/* Mark NHLFE as changed. */
|
||||
SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED);
|
||||
added++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Queue LSP for processing if necessary. If no NHLFE got added (special
|
||||
* case), delete the LSP entry; this case results in somewhat ugly logging.
|
||||
*/
|
||||
if (added || changed)
|
||||
{
|
||||
if (lsp_processq_add (lsp))
|
||||
return -1;
|
||||
}
|
||||
else if (!lsp->nhlfe_list &&
|
||||
!CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED))
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_MPLS)
|
||||
zlog_debug ("Free LSP in-label %u flags 0x%x",
|
||||
lsp->ile.in_label, lsp->flags);
|
||||
|
||||
lsp = hash_release(lsp_table, &lsp->ile);
|
||||
if (lsp)
|
||||
XFREE(MTYPE_LSP, lsp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Uninstall all non-static NHLFEs of a label forwarding entry. If all
|
||||
* NHLFEs are removed, the entire entry is deleted.
|
||||
*/
|
||||
static int
|
||||
lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label)
|
||||
{
|
||||
struct hash *lsp_table;
|
||||
zebra_ile_t tmp_ile;
|
||||
zebra_lsp_t *lsp;
|
||||
zebra_nhlfe_t *nhlfe, *nhlfe_next;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
/* Lookup table. */
|
||||
lsp_table = zvrf->lsp_table;
|
||||
if (!lsp_table)
|
||||
return -1;
|
||||
|
||||
/* If entry is not present, exit. */
|
||||
tmp_ile.in_label = label;
|
||||
lsp = hash_lookup (lsp_table, &tmp_ile);
|
||||
if (!lsp || !lsp->nhlfe_list)
|
||||
return 0;
|
||||
|
||||
/* Mark NHLFEs for delete or directly delete, as appropriate. */
|
||||
for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next)
|
||||
{
|
||||
nhlfe_next = nhlfe->next;
|
||||
|
||||
/* Skip static NHLFEs */
|
||||
if (nhlfe->type == ZEBRA_LSP_STATIC)
|
||||
continue;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_MPLS)
|
||||
{
|
||||
nhlfe2str (nhlfe, buf, BUFSIZ);
|
||||
zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x",
|
||||
label, nhlfe->type, buf, nhlfe->flags);
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED))
|
||||
{
|
||||
UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
|
||||
SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
|
||||
}
|
||||
else
|
||||
{
|
||||
nhlfe_del (nhlfe);
|
||||
}
|
||||
}
|
||||
|
||||
/* Queue LSP for processing, if needed, else delete. */
|
||||
if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED))
|
||||
{
|
||||
if (lsp_processq_add (lsp))
|
||||
return -1;
|
||||
}
|
||||
else if (!lsp->nhlfe_list &&
|
||||
!CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED))
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_MPLS)
|
||||
zlog_debug ("Del LSP in-label %u flags 0x%x",
|
||||
lsp->ile.in_label, lsp->flags);
|
||||
|
||||
lsp = hash_release(lsp_table, &lsp->ile);
|
||||
if (lsp)
|
||||
XFREE(MTYPE_LSP, lsp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* There is a change for this FEC. Install or uninstall label forwarding
|
||||
* entries, as appropriate.
|
||||
*/
|
||||
static int
|
||||
fec_change_update_lsp (struct zebra_vrf *zvrf, zebra_fec_t *fec, mpls_label_t old_label)
|
||||
{
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
struct rib *rib;
|
||||
afi_t afi;
|
||||
|
||||
/* Uninstall label forwarding entry, if previously installed. */
|
||||
if (old_label != MPLS_INVALID_LABEL &&
|
||||
old_label != MPLS_IMP_NULL_LABEL)
|
||||
lsp_uninstall (zvrf, old_label);
|
||||
|
||||
/* Install label forwarding entry corr. to new label, if needed. */
|
||||
if (fec->label == MPLS_INVALID_LABEL ||
|
||||
fec->label == MPLS_IMP_NULL_LABEL)
|
||||
return 0;
|
||||
|
||||
afi = family2afi(PREFIX_FAMILY(&fec->rn->p));
|
||||
table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf_id (zvrf));
|
||||
if (!table)
|
||||
return 0;
|
||||
|
||||
/* See if labeled route exists. */
|
||||
rn = route_node_lookup (table, &fec->rn->p);
|
||||
if (!rn)
|
||||
return 0;
|
||||
|
||||
RNODE_FOREACH_RIB (rn, rib)
|
||||
{
|
||||
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!rib || !zebra_rib_labeled_unicast (rib))
|
||||
return 0;
|
||||
|
||||
if (lsp_install (zvrf, fec->label, rn, rib))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inform about FEC to a registered client.
|
||||
*/
|
||||
@ -760,7 +1007,7 @@ nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size)
|
||||
*/
|
||||
static int
|
||||
nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex)
|
||||
union g_addr *gate, ifindex_t ifindex)
|
||||
{
|
||||
struct nexthop *nhop;
|
||||
int cmp = 1;
|
||||
@ -802,7 +1049,7 @@ nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype,
|
||||
static zebra_nhlfe_t *
|
||||
nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
|
||||
enum nexthop_types_t gtype, union g_addr *gate,
|
||||
char *ifname, ifindex_t ifindex)
|
||||
ifindex_t ifindex)
|
||||
{
|
||||
zebra_nhlfe_t *nhlfe;
|
||||
|
||||
@ -813,7 +1060,7 @@ nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
|
||||
{
|
||||
if (nhlfe->type != lsp_type)
|
||||
continue;
|
||||
if (!nhlfe_nhop_match (nhlfe, gtype, gate, ifname, ifindex))
|
||||
if (!nhlfe_nhop_match (nhlfe, gtype, gate, ifindex))
|
||||
break;
|
||||
}
|
||||
|
||||
@ -827,7 +1074,7 @@ nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
|
||||
static zebra_nhlfe_t *
|
||||
nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
|
||||
enum nexthop_types_t gtype, union g_addr *gate,
|
||||
char *ifname, ifindex_t ifindex, mpls_label_t out_label)
|
||||
ifindex_t ifindex, mpls_label_t out_label)
|
||||
{
|
||||
zebra_nhlfe_t *nhlfe;
|
||||
struct nexthop *nexthop;
|
||||
@ -917,6 +1164,15 @@ nhlfe_del (zebra_nhlfe_t *nhlfe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update label for NHLFE entry.
|
||||
*/
|
||||
static void
|
||||
nhlfe_out_label_update (zebra_nhlfe_t *nhlfe, struct nexthop_label *nh_label)
|
||||
{
|
||||
nhlfe->nexthop->nh_label->label[0] = nh_label->label[0];
|
||||
}
|
||||
|
||||
static int
|
||||
mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp,
|
||||
enum lsp_types_t type)
|
||||
@ -1184,7 +1440,7 @@ slsp_cmp (zebra_slsp_t *slsp1, zebra_slsp_t *slsp2)
|
||||
*/
|
||||
static int
|
||||
snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex)
|
||||
union g_addr *gate, ifindex_t ifindex)
|
||||
{
|
||||
int cmp = 1;
|
||||
|
||||
@ -1216,7 +1472,7 @@ snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
|
||||
*/
|
||||
static zebra_snhlfe_t *
|
||||
snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex)
|
||||
union g_addr *gate, ifindex_t ifindex)
|
||||
{
|
||||
zebra_snhlfe_t *snhlfe;
|
||||
|
||||
@ -1225,7 +1481,7 @@ snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
|
||||
|
||||
for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next)
|
||||
{
|
||||
if (!snhlfe_match (snhlfe, gtype, gate, ifname, ifindex))
|
||||
if (!snhlfe_match (snhlfe, gtype, gate, ifindex))
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1239,7 +1495,7 @@ snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
|
||||
*/
|
||||
static zebra_snhlfe_t *
|
||||
snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex,
|
||||
union g_addr *gate, ifindex_t ifindex,
|
||||
mpls_label_t out_label)
|
||||
{
|
||||
zebra_snhlfe_t *snhlfe;
|
||||
@ -1388,7 +1644,7 @@ mpls_str2label (const char *label_str, u_int8_t *num_labels,
|
||||
*num_labels = 0;
|
||||
for (i = 0; i < MPLS_MAX_LABELS; i++)
|
||||
{
|
||||
u_int32_t label;
|
||||
mpls_label_t label;
|
||||
|
||||
label = strtoul(label_str, &endp, 0);
|
||||
|
||||
@ -1432,6 +1688,58 @@ mpls_label2str (u_int8_t num_labels, mpls_label_t *labels,
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Install dynamic LSP entry.
|
||||
*/
|
||||
int
|
||||
zebra_mpls_lsp_install (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *rib)
|
||||
{
|
||||
struct route_table *table;
|
||||
zebra_fec_t *fec;
|
||||
|
||||
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))];
|
||||
if (!table)
|
||||
return -1;
|
||||
|
||||
/* See if there is a configured label binding for this FEC. */
|
||||
fec = fec_find (table, &rn->p);
|
||||
if (!fec || fec->label == MPLS_INVALID_LABEL)
|
||||
return 0;
|
||||
|
||||
/* We cannot install a label forwarding entry if local label is the
|
||||
* implicit-null label.
|
||||
*/
|
||||
if (fec->label == MPLS_IMP_NULL_LABEL)
|
||||
return 0;
|
||||
|
||||
if (lsp_install (zvrf, fec->label, rn, rib))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Uninstall dynamic LSP entry, if any.
|
||||
*/
|
||||
int
|
||||
zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *rib)
|
||||
{
|
||||
struct route_table *table;
|
||||
zebra_fec_t *fec;
|
||||
|
||||
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))];
|
||||
if (!table)
|
||||
return -1;
|
||||
|
||||
/* See if there is a configured label binding for this FEC. */
|
||||
fec = fec_find (table, &rn->p);
|
||||
if (!fec || fec->label == MPLS_INVALID_LABEL)
|
||||
return 0;
|
||||
|
||||
/* Uninstall always removes all dynamic NHLFEs. */
|
||||
return lsp_uninstall (zvrf, fec->label);
|
||||
}
|
||||
|
||||
/*
|
||||
* Registration from a client for the label binding for a FEC. If a binding
|
||||
* already exists, it is informed to the client.
|
||||
@ -1611,7 +1919,8 @@ zebra_mpls_label_already_bound (struct zebra_vrf *zvrf, mpls_label_t label)
|
||||
|
||||
/*
|
||||
* Add static FEC to label binding. If there are clients registered for this
|
||||
* FEC, notify them.
|
||||
* FEC, notify them. If there are labeled routes for this FEC, install the
|
||||
* label forwarding entry.
|
||||
*/
|
||||
int
|
||||
zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p,
|
||||
@ -1620,6 +1929,7 @@ zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p,
|
||||
struct route_table *table;
|
||||
zebra_fec_t *fec;
|
||||
char buf[BUFSIZ];
|
||||
mpls_label_t old_label;
|
||||
int ret = 0;
|
||||
|
||||
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
|
||||
@ -1652,11 +1962,15 @@ zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p,
|
||||
return 0;
|
||||
|
||||
/* Label change, update clients. */
|
||||
old_label = fec->label;
|
||||
if (IS_ZEBRA_DEBUG_MPLS)
|
||||
zlog_debug ("Update fec %s new label %u", buf, in_label);
|
||||
|
||||
fec->label = in_label;
|
||||
fec_update_clients (fec);
|
||||
|
||||
/* Update label forwarding entries appropriately */
|
||||
ret = fec_change_update_lsp (zvrf, fec, old_label);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1671,6 +1985,7 @@ zebra_mpls_static_fec_del (struct zebra_vrf *zvrf, struct prefix *p)
|
||||
{
|
||||
struct route_table *table;
|
||||
zebra_fec_t *fec;
|
||||
mpls_label_t old_label;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
|
||||
@ -1691,6 +2006,7 @@ zebra_mpls_static_fec_del (struct zebra_vrf *zvrf, struct prefix *p)
|
||||
zlog_debug ("Delete fec %s", buf);
|
||||
}
|
||||
|
||||
old_label = fec->label;
|
||||
fec->flags &= ~FEC_FLAG_CONFIGURED;
|
||||
fec->label = MPLS_INVALID_LABEL;
|
||||
|
||||
@ -1703,7 +2019,8 @@ zebra_mpls_static_fec_del (struct zebra_vrf *zvrf, struct prefix *p)
|
||||
|
||||
fec_update_clients (fec);
|
||||
|
||||
return 0;
|
||||
/* Update label forwarding entries appropriately */
|
||||
return fec_change_update_lsp (zvrf, fec, old_label);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1879,7 +2196,7 @@ int
|
||||
mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
mpls_label_t in_label, mpls_label_t out_label,
|
||||
enum nexthop_types_t gtype, union g_addr *gate,
|
||||
char *ifname, ifindex_t ifindex)
|
||||
ifindex_t ifindex)
|
||||
{
|
||||
struct hash *lsp_table;
|
||||
zebra_ile_t tmp_ile;
|
||||
@ -1897,7 +2214,7 @@ mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc);
|
||||
if (!lsp)
|
||||
return -1;
|
||||
nhlfe = nhlfe_find (lsp, type, gtype, gate, ifname, ifindex);
|
||||
nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex);
|
||||
if (nhlfe)
|
||||
{
|
||||
struct nexthop *nh = nhlfe->nexthop;
|
||||
@ -1926,8 +2243,7 @@ mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
else
|
||||
{
|
||||
/* Add LSP entry to this nexthop */
|
||||
nhlfe = nhlfe_add (lsp, type, gtype, gate,
|
||||
ifname, ifindex, out_label);
|
||||
nhlfe = nhlfe_add (lsp, type, gtype, gate, ifindex, out_label);
|
||||
if (!nhlfe)
|
||||
return -1;
|
||||
|
||||
@ -1956,7 +2272,7 @@ mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
int
|
||||
mpls_lsp_uninstall (struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
mpls_label_t in_label, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex)
|
||||
union g_addr *gate, ifindex_t ifindex)
|
||||
{
|
||||
struct hash *lsp_table;
|
||||
zebra_ile_t tmp_ile;
|
||||
@ -1974,7 +2290,7 @@ mpls_lsp_uninstall (struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
lsp = hash_lookup (lsp_table, &tmp_ile);
|
||||
if (!lsp)
|
||||
return 0;
|
||||
nhlfe = nhlfe_find (lsp, type, gtype, gate, ifname, ifindex);
|
||||
nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex);
|
||||
if (!nhlfe)
|
||||
return 0;
|
||||
|
||||
@ -2079,7 +2395,7 @@ mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi)
|
||||
int
|
||||
zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
mpls_label_t out_label, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex)
|
||||
union g_addr *gate, ifindex_t ifindex)
|
||||
{
|
||||
struct hash *slsp_table;
|
||||
zebra_ile_t tmp_ile;
|
||||
@ -2097,7 +2413,7 @@ zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
if (!slsp)
|
||||
return 1;
|
||||
|
||||
snhlfe = snhlfe_find (slsp, gtype, gate, ifname, ifindex);
|
||||
snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
|
||||
if (snhlfe)
|
||||
{
|
||||
if (snhlfe->out_label == out_label)
|
||||
@ -2137,7 +2453,7 @@ zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
int
|
||||
zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
mpls_label_t out_label, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex)
|
||||
union g_addr *gate, ifindex_t ifindex)
|
||||
{
|
||||
struct hash *slsp_table;
|
||||
zebra_ile_t tmp_ile;
|
||||
@ -2155,7 +2471,7 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
slsp = hash_get (slsp_table, &tmp_ile, slsp_alloc);
|
||||
if (!slsp)
|
||||
return -1;
|
||||
snhlfe = snhlfe_find (slsp, gtype, gate, ifname, ifindex);
|
||||
snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
|
||||
if (snhlfe)
|
||||
{
|
||||
if (snhlfe->out_label == out_label)
|
||||
@ -2174,7 +2490,7 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
else
|
||||
{
|
||||
/* Add static LSP entry to this nexthop */
|
||||
snhlfe = snhlfe_add (slsp, gtype, gate, ifname, ifindex, out_label);
|
||||
snhlfe = snhlfe_add (slsp, gtype, gate, ifindex, out_label);
|
||||
if (!snhlfe)
|
||||
return -1;
|
||||
|
||||
@ -2188,7 +2504,7 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
|
||||
/* (Re)Install LSP in the main table. */
|
||||
if (mpls_lsp_install (zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype,
|
||||
gate, ifname, ifindex))
|
||||
gate, ifindex))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@ -2204,7 +2520,7 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
int
|
||||
zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
enum nexthop_types_t gtype, union g_addr *gate,
|
||||
char *ifname, ifindex_t ifindex)
|
||||
ifindex_t ifindex)
|
||||
{
|
||||
struct hash *slsp_table;
|
||||
zebra_ile_t tmp_ile;
|
||||
@ -2237,7 +2553,7 @@ zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
else
|
||||
{
|
||||
/* Find specific NHLFE, exit if not found. */
|
||||
snhlfe = snhlfe_find (slsp, gtype, gate, ifname, ifindex);
|
||||
snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
|
||||
if (!snhlfe)
|
||||
return 0;
|
||||
|
||||
@ -2251,7 +2567,7 @@ zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
|
||||
/* Uninstall LSP from the main table. */
|
||||
mpls_lsp_uninstall (zvrf, ZEBRA_LSP_STATIC, in_label, gtype, gate,
|
||||
ifname, ifindex);
|
||||
ifindex);
|
||||
|
||||
/* Delete static LSP NHLFE */
|
||||
snhlfe_del (snhlfe);
|
||||
|
@ -183,6 +183,18 @@ char *
|
||||
mpls_label2str (u_int8_t num_labels, mpls_label_t *labels,
|
||||
char *buf, int len);
|
||||
|
||||
/*
|
||||
* Install dynamic LSP entry.
|
||||
*/
|
||||
int
|
||||
zebra_mpls_lsp_install (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *rib);
|
||||
|
||||
/*
|
||||
* Uninstall dynamic LSP entry, if any.
|
||||
*/
|
||||
int
|
||||
zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *rib);
|
||||
|
||||
/*
|
||||
* Registration from a client for the label binding for a FEC. If a binding
|
||||
* already exists, it is informed to the client.
|
||||
@ -224,7 +236,8 @@ zebra_mpls_label_already_bound (struct zebra_vrf *zvrf, mpls_label_t label);
|
||||
|
||||
/*
|
||||
* Add static FEC to label binding. If there are clients registered for this
|
||||
* FEC, notify them.
|
||||
* FEC, notify them. If there are labeled routes for this FEC, install the
|
||||
* label forwarding entry.
|
||||
*/
|
||||
int
|
||||
zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p,
|
||||
@ -273,7 +286,7 @@ int
|
||||
mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
mpls_label_t in_label, mpls_label_t out_label,
|
||||
enum nexthop_types_t gtype, union g_addr *gate,
|
||||
char *ifname, ifindex_t ifindex);
|
||||
ifindex_t ifindex);
|
||||
|
||||
/*
|
||||
* Uninstall a particular NHLFE in the forwarding table. If this is
|
||||
@ -282,7 +295,7 @@ mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
int
|
||||
mpls_lsp_uninstall (struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
mpls_label_t in_label, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex);
|
||||
union g_addr *gate, ifindex_t ifindex);
|
||||
|
||||
/*
|
||||
* Uninstall all LDP NHLFEs for a particular LSP forwarding entry.
|
||||
@ -307,7 +320,7 @@ mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi);
|
||||
int
|
||||
zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
mpls_label_t out_label, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex);
|
||||
union g_addr *gate, ifindex_t ifindex);
|
||||
#endif /* HAVE_CUMULUS */
|
||||
|
||||
/*
|
||||
@ -320,7 +333,7 @@ zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
int
|
||||
zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
mpls_label_t out_label, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex);
|
||||
union g_addr *gate, ifindex_t ifindex);
|
||||
|
||||
/*
|
||||
* Delete static LSP entry. This may be the delete of one particular
|
||||
@ -332,7 +345,7 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
int
|
||||
zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
enum nexthop_types_t gtype, union g_addr *gate,
|
||||
char *ifname, ifindex_t ifindex);
|
||||
ifindex_t ifindex);
|
||||
|
||||
/*
|
||||
* Schedule all MPLS label forwarding entries for processing.
|
||||
@ -415,6 +428,8 @@ lsp_type_from_rib_type (int rib_type)
|
||||
{
|
||||
case ZEBRA_ROUTE_STATIC:
|
||||
return ZEBRA_LSP_STATIC;
|
||||
case ZEBRA_ROUTE_BGP:
|
||||
return ZEBRA_LSP_BGP;
|
||||
default:
|
||||
return ZEBRA_LSP_NONE;
|
||||
}
|
||||
@ -430,6 +445,8 @@ nhlfe_type2str(enum lsp_types_t lsp_type)
|
||||
return "Static";
|
||||
case ZEBRA_LSP_LDP:
|
||||
return "LDP";
|
||||
case ZEBRA_LSP_BGP:
|
||||
return "BGP";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
@ -44,6 +44,18 @@ mpls_str2label (const char *label_str, u_int8_t *num_labels,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
zebra_mpls_lsp_install (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *rib)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *rib)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
zebra_mpls_init_tables (struct zebra_vrf *zvrf)
|
||||
{
|
||||
@ -70,7 +82,7 @@ zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf)
|
||||
int
|
||||
zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
mpls_label_t out_label, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex)
|
||||
union g_addr *gate, ifindex_t ifindex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -78,7 +90,7 @@ zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
int
|
||||
zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
mpls_label_t out_label, enum nexthop_types_t gtype,
|
||||
union g_addr *gate, char *ifname, ifindex_t ifindex)
|
||||
union g_addr *gate, ifindex_t ifindex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -86,7 +98,7 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
int
|
||||
zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label,
|
||||
enum nexthop_types_t gtype, union g_addr *gate,
|
||||
char *ifname, ifindex_t ifindex)
|
||||
ifindex_t ifindex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ zebra_mpls_transit_lsp (struct vty *vty, int add_cmd, const char *inlabel_str,
|
||||
#if defined(HAVE_CUMULUS)
|
||||
/* Check that label value is consistent. */
|
||||
if (!zebra_mpls_lsp_label_consistent (zvrf, in_label, out_label, gtype,
|
||||
&gate, NULL, 0))
|
||||
&gate, 0))
|
||||
{
|
||||
vty_out (vty, "%% Label value not consistent%s",
|
||||
VTY_NEWLINE);
|
||||
@ -142,10 +142,10 @@ zebra_mpls_transit_lsp (struct vty *vty, int add_cmd, const char *inlabel_str,
|
||||
#endif /* HAVE_CUMULUS */
|
||||
|
||||
ret = zebra_mpls_static_lsp_add (zvrf, in_label, out_label, gtype,
|
||||
&gate, NULL, 0);
|
||||
&gate, 0);
|
||||
}
|
||||
else
|
||||
ret = zebra_mpls_static_lsp_del (zvrf, in_label, gtype, &gate, NULL, 0);
|
||||
ret = zebra_mpls_static_lsp_del (zvrf, in_label, gtype, &gate, 0);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
|
@ -1084,7 +1084,25 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
|
||||
return rib->nexthop_active_num;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this RIB labeled-unicast? It must be of type BGP and all paths
|
||||
* (nexthops) must have a label.
|
||||
*/
|
||||
int
|
||||
zebra_rib_labeled_unicast (struct rib *rib)
|
||||
{
|
||||
struct nexthop *nexthop = NULL, *tnexthop;
|
||||
int recursing;
|
||||
|
||||
if (rib->type != ZEBRA_ROUTE_BGP)
|
||||
return 0;
|
||||
|
||||
for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
|
||||
if (!nexthop->nh_label || !nexthop->nh_label->num_labels)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Update flag indicates whether this is a "replace" or not. Currently, this
|
||||
* is only used for IPv4.
|
||||
@ -1177,7 +1195,12 @@ rib_uninstall (struct route_node *rn, struct rib *rib)
|
||||
|
||||
if (! RIB_SYSTEM_ROUTE (rib))
|
||||
rib_uninstall_kernel (rn, rib);
|
||||
UNSET_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB);
|
||||
|
||||
/* If labeled-unicast route, uninstall transit LSP. */
|
||||
if (zebra_rib_labeled_unicast (rib))
|
||||
zebra_mpls_lsp_uninstall (info->zvrf, rn, rib);
|
||||
|
||||
UNSET_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB);
|
||||
}
|
||||
|
||||
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
|
||||
@ -1272,6 +1295,10 @@ rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
zvrf_id (zvrf), buf, rn, new, new->type);
|
||||
}
|
||||
|
||||
/* If labeled-unicast route, install transit LSP. */
|
||||
if (zebra_rib_labeled_unicast (new))
|
||||
zebra_mpls_lsp_install (zvrf, rn, new);
|
||||
|
||||
if (!RIB_SYSTEM_ROUTE (new))
|
||||
{
|
||||
if (rib_install_kernel (rn, new, NULL))
|
||||
@ -1301,6 +1328,10 @@ rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
zvrf_id (zvrf), buf, rn, old, old->type);
|
||||
}
|
||||
|
||||
/* If labeled-unicast route, uninstall transit LSP. */
|
||||
if (zebra_rib_labeled_unicast (old))
|
||||
zebra_mpls_lsp_uninstall (zvrf, rn, old);
|
||||
|
||||
if (!RIB_SYSTEM_ROUTE (old))
|
||||
rib_uninstall_kernel (rn, old);
|
||||
|
||||
@ -1354,6 +1385,10 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
/* Non-system route should be installed. */
|
||||
if (!RIB_SYSTEM_ROUTE (new))
|
||||
{
|
||||
/* If labeled-unicast route, install transit LSP. */
|
||||
if (zebra_rib_labeled_unicast (new))
|
||||
zebra_mpls_lsp_install (zvrf, rn, new);
|
||||
|
||||
if (rib_install_kernel (rn, new, old))
|
||||
{
|
||||
char buf[SRCDEST2STR_BUFFER];
|
||||
@ -1368,6 +1403,10 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
{
|
||||
if (RIB_SYSTEM_ROUTE(new))
|
||||
{
|
||||
/* If labeled-unicast route, uninstall transit LSP. */
|
||||
if (zebra_rib_labeled_unicast (old))
|
||||
zebra_mpls_lsp_uninstall (zvrf, rn, old);
|
||||
|
||||
if (!RIB_SYSTEM_ROUTE (old))
|
||||
rib_uninstall_kernel (rn, old);
|
||||
}
|
||||
@ -1404,6 +1443,10 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
nh_active ? "install failed" : "nexthop inactive");
|
||||
}
|
||||
|
||||
/* If labeled-unicast route, uninstall transit LSP. */
|
||||
if (zebra_rib_labeled_unicast (old))
|
||||
zebra_mpls_lsp_uninstall (zvrf, rn, old);
|
||||
|
||||
if (!RIB_SYSTEM_ROUTE (old))
|
||||
rib_uninstall_kernel (rn, old);
|
||||
UNSET_FLAG (new->status, RIB_ENTRY_SELECTED_FIB);
|
||||
@ -2934,8 +2977,10 @@ rib_tables_iter_next (rib_tables_iter_t *iter)
|
||||
} afi_safis[] = {
|
||||
{ AFI_IP, SAFI_UNICAST },
|
||||
{ AFI_IP, SAFI_MULTICAST },
|
||||
{ AFI_IP, SAFI_LABELED_UNICAST },
|
||||
{ AFI_IP6, SAFI_UNICAST },
|
||||
{ AFI_IP6, SAFI_MULTICAST },
|
||||
{ AFI_IP6, SAFI_LABELED_UNICAST },
|
||||
};
|
||||
|
||||
table = NULL;
|
||||
|
@ -1129,13 +1129,15 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
|
||||
struct rib *rib;
|
||||
struct prefix p;
|
||||
u_char message;
|
||||
struct in_addr nexthop;
|
||||
struct in_addr nhop_addr;
|
||||
u_char nexthop_num;
|
||||
u_char nexthop_type;
|
||||
struct stream *s;
|
||||
ifindex_t ifindex;
|
||||
safi_t safi;
|
||||
int ret;
|
||||
mpls_label_t label;
|
||||
struct nexthop *nexthop;
|
||||
|
||||
/* Get input stream. */
|
||||
s = client->ibuf;
|
||||
@ -1177,13 +1179,19 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
|
||||
rib_nexthop_ifindex_add (rib, ifindex);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
nexthop.s_addr = stream_get_ipv4 (s);
|
||||
rib_nexthop_ipv4_add (rib, &nexthop, NULL);
|
||||
nhop_addr.s_addr = stream_get_ipv4 (s);
|
||||
nexthop = rib_nexthop_ipv4_add (rib, &nhop_addr, NULL);
|
||||
/* For labeled-unicast, each nexthop is followed by label. */
|
||||
if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL))
|
||||
{
|
||||
label = (mpls_label_t)stream_getl (s);
|
||||
nexthop_add_labels (nexthop, nexthop->nh_label_type, 1, &label);
|
||||
}
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
nexthop.s_addr = stream_get_ipv4 (s);
|
||||
nhop_addr.s_addr = stream_get_ipv4 (s);
|
||||
ifindex = stream_getl (s);
|
||||
rib_nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex);
|
||||
rib_nexthop_ipv4_ifindex_add (rib, &nhop_addr, NULL, ifindex);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
stream_forward_getp (s, IPV6_MAX_BYTELEN);
|
||||
@ -1276,6 +1284,11 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
nexthop.s_addr = stream_get_ipv4 (s);
|
||||
/* For labeled-unicast, each nexthop is followed by label, but
|
||||
* we don't care for delete.
|
||||
*/
|
||||
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_LABEL))
|
||||
stream_forward_getp (s, sizeof(u_int32_t));
|
||||
nexthop_p = (union g_addr *)&nexthop;
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
@ -1461,7 +1474,7 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
|
||||
{
|
||||
unsigned int i;
|
||||
struct stream *s;
|
||||
struct in6_addr nexthop;
|
||||
struct in6_addr nhop_addr;
|
||||
struct rib *rib;
|
||||
u_char message;
|
||||
u_char nexthop_num;
|
||||
@ -1472,11 +1485,14 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
|
||||
static struct in6_addr nexthops[MULTIPATH_NUM];
|
||||
static unsigned int ifindices[MULTIPATH_NUM];
|
||||
int ret;
|
||||
static mpls_label_t labels[MULTIPATH_NUM];
|
||||
mpls_label_t label;
|
||||
struct nexthop *nexthop;
|
||||
|
||||
/* Get input stream. */
|
||||
s = client->ibuf;
|
||||
|
||||
memset (&nexthop, 0, sizeof (struct in6_addr));
|
||||
memset (&nhop_addr, 0, sizeof (struct in6_addr));
|
||||
|
||||
/* Allocate new rib. */
|
||||
rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
|
||||
@ -1525,10 +1541,17 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
|
||||
switch (nexthop_type)
|
||||
{
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
stream_get (&nexthop, s, 16);
|
||||
if (nh_count < multipath_num) {
|
||||
nexthops[nh_count++] = nexthop;
|
||||
}
|
||||
stream_get (&nhop_addr, s, 16);
|
||||
if (nh_count < MULTIPATH_NUM)
|
||||
{
|
||||
/* For labeled-unicast, each nexthop is followed by label. */
|
||||
if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL))
|
||||
{
|
||||
label = (mpls_label_t)stream_getl (s);
|
||||
labels[nh_count++] = label;
|
||||
}
|
||||
nexthops[nh_count++] = nhop_addr;
|
||||
}
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
if (if_count < multipath_num) {
|
||||
@ -1546,9 +1569,11 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
|
||||
{
|
||||
if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) {
|
||||
if ((i < if_count) && ifindices[i])
|
||||
rib_nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]);
|
||||
nexthop = rib_nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]);
|
||||
else
|
||||
rib_nexthop_ipv6_add (rib, &nexthops[i]);
|
||||
nexthop = rib_nexthop_ipv6_add (rib, &nexthops[i]);
|
||||
if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL))
|
||||
nexthop_add_labels (nexthop, nexthop->nh_label_type, 1, &labels[i]);
|
||||
}
|
||||
else {
|
||||
if ((i < if_count) && ifindices[i])
|
||||
@ -1645,6 +1670,11 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
|
||||
{
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
stream_get (&nexthop, s, 16);
|
||||
/* For labeled-unicast, each nexthop is followed by label, but
|
||||
* we don't care for delete.
|
||||
*/
|
||||
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_LABEL))
|
||||
stream_forward_getp (s, sizeof(u_int32_t));
|
||||
pnexthop = (union g_addr *)&nexthop;
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
@ -1815,14 +1845,14 @@ zread_mpls_labels (int command, struct zserv *client, u_short length,
|
||||
if (command == ZEBRA_MPLS_LABELS_ADD)
|
||||
{
|
||||
mpls_lsp_install (zvrf, type, in_label, out_label, gtype, &gate,
|
||||
NULL, ifindex);
|
||||
ifindex);
|
||||
if (out_label != MPLS_IMP_NULL_LABEL)
|
||||
mpls_ftn_update (1, zvrf, type, &prefix, gtype, &gate, ifindex,
|
||||
distance, out_label);
|
||||
}
|
||||
else if (command == ZEBRA_MPLS_LABELS_DELETE)
|
||||
{
|
||||
mpls_lsp_uninstall (zvrf, type, in_label, gtype, &gate, NULL, ifindex);
|
||||
mpls_lsp_uninstall (zvrf, type, in_label, gtype, &gate, ifindex);
|
||||
if (out_label != MPLS_IMP_NULL_LABEL)
|
||||
mpls_ftn_update (0, zvrf, type, &prefix, gtype, &gate, ifindex,
|
||||
distance, out_label);
|
||||
|
Loading…
Reference in New Issue
Block a user