mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 07:30:53 +00:00
ldpd: implement RFC 5918 (Typed Wildcard FEC)
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
parent
8819fc38a0
commit
d4afb81972
68
ldpd/init.c
68
ldpd/init.c
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
static int gen_init_prms_tlv(struct ibuf *, struct nbr *);
|
static int gen_init_prms_tlv(struct ibuf *, struct nbr *);
|
||||||
static int gen_cap_dynamic_tlv(struct ibuf *);
|
static int gen_cap_dynamic_tlv(struct ibuf *);
|
||||||
|
static int gen_cap_twcard_tlv(struct ibuf *, int);
|
||||||
|
|
||||||
void
|
void
|
||||||
send_init(struct nbr *nbr)
|
send_init(struct nbr *nbr)
|
||||||
@ -36,7 +37,7 @@ send_init(struct nbr *nbr)
|
|||||||
debug_msg_send("initialization: lsr-id %s", inet_ntoa(nbr->id));
|
debug_msg_send("initialization: lsr-id %s", inet_ntoa(nbr->id));
|
||||||
|
|
||||||
size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE +
|
size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE +
|
||||||
CAP_TLV_DYNAMIC_SIZE;
|
CAP_TLV_DYNAMIC_SIZE + CAP_TLV_TWCARD_SIZE;
|
||||||
if ((buf = ibuf_open(size)) == NULL)
|
if ((buf = ibuf_open(size)) == NULL)
|
||||||
fatal(__func__);
|
fatal(__func__);
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ send_init(struct nbr *nbr)
|
|||||||
err |= gen_msg_hdr(buf, MSG_TYPE_INIT, size);
|
err |= gen_msg_hdr(buf, MSG_TYPE_INIT, size);
|
||||||
err |= gen_init_prms_tlv(buf, nbr);
|
err |= gen_init_prms_tlv(buf, nbr);
|
||||||
err |= gen_cap_dynamic_tlv(buf);
|
err |= gen_cap_dynamic_tlv(buf);
|
||||||
|
err |= gen_cap_twcard_tlv(buf, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
ibuf_free(buf);
|
ibuf_free(buf);
|
||||||
return;
|
return;
|
||||||
@ -146,6 +148,25 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
|
|||||||
"Capability Announcement capability", __func__,
|
"Capability Announcement capability", __func__,
|
||||||
inet_ntoa(nbr->id));
|
inet_ntoa(nbr->id));
|
||||||
break;
|
break;
|
||||||
|
case TLV_TYPE_TWCARD_CAP:
|
||||||
|
if (tlv_len != CAP_TLV_TWCARD_LEN) {
|
||||||
|
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
|
||||||
|
msg.type);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caps_rcvd & F_CAP_TLV_RCVD_TWCARD) {
|
||||||
|
session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
|
||||||
|
msg.type);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
caps_rcvd |= F_CAP_TLV_RCVD_TWCARD;
|
||||||
|
|
||||||
|
nbr->flags |= F_NBR_CAP_TWCARD;
|
||||||
|
|
||||||
|
log_debug("%s: lsr-id %s announced the Typed Wildcard "
|
||||||
|
"FEC capability", __func__, inet_ntoa(nbr->id));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
|
if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
|
||||||
send_notification_rtlvs(nbr, S_UNSSUPORTDCAP,
|
send_notification_rtlvs(nbr, S_UNSSUPORTDCAP,
|
||||||
@ -193,6 +214,9 @@ send_capability(struct nbr *nbr, uint16_t capability, int enable)
|
|||||||
err |= gen_msg_hdr(buf, MSG_TYPE_CAPABILITY, size);
|
err |= gen_msg_hdr(buf, MSG_TYPE_CAPABILITY, size);
|
||||||
|
|
||||||
switch (capability) {
|
switch (capability) {
|
||||||
|
case TLV_TYPE_TWCARD_CAP:
|
||||||
|
err |= gen_cap_twcard_tlv(buf, enable);
|
||||||
|
break;
|
||||||
case TLV_TYPE_DYNAMIC_CAP:
|
case TLV_TYPE_DYNAMIC_CAP:
|
||||||
/*
|
/*
|
||||||
* RFC 5561 - Section 9:
|
* RFC 5561 - Section 9:
|
||||||
@ -218,6 +242,8 @@ int
|
|||||||
recv_capability(struct nbr *nbr, char *buf, uint16_t len)
|
recv_capability(struct nbr *nbr, char *buf, uint16_t len)
|
||||||
{
|
{
|
||||||
struct ldp_msg msg;
|
struct ldp_msg msg;
|
||||||
|
int enable = 0;
|
||||||
|
int caps_rcvd = 0;
|
||||||
|
|
||||||
log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
|
log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
|
||||||
|
|
||||||
@ -230,6 +256,7 @@ recv_capability(struct nbr *nbr, char *buf, uint16_t len)
|
|||||||
struct tlv tlv;
|
struct tlv tlv;
|
||||||
uint16_t tlv_type;
|
uint16_t tlv_type;
|
||||||
uint16_t tlv_len;
|
uint16_t tlv_len;
|
||||||
|
uint8_t reserved;
|
||||||
|
|
||||||
if (len < sizeof(tlv)) {
|
if (len < sizeof(tlv)) {
|
||||||
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
|
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
|
||||||
@ -247,6 +274,31 @@ recv_capability(struct nbr *nbr, char *buf, uint16_t len)
|
|||||||
len -= TLV_HDR_SIZE;
|
len -= TLV_HDR_SIZE;
|
||||||
|
|
||||||
switch (tlv_type) {
|
switch (tlv_type) {
|
||||||
|
case TLV_TYPE_TWCARD_CAP:
|
||||||
|
if (tlv_len != CAP_TLV_TWCARD_LEN) {
|
||||||
|
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
|
||||||
|
msg.type);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caps_rcvd & F_CAP_TLV_RCVD_TWCARD) {
|
||||||
|
session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
|
||||||
|
msg.type);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
caps_rcvd |= F_CAP_TLV_RCVD_TWCARD;
|
||||||
|
|
||||||
|
memcpy(&reserved, buf, sizeof(reserved));
|
||||||
|
enable = reserved & STATE_BIT;
|
||||||
|
if (enable)
|
||||||
|
nbr->flags |= F_NBR_CAP_TWCARD;
|
||||||
|
else
|
||||||
|
nbr->flags &= ~F_NBR_CAP_TWCARD;
|
||||||
|
|
||||||
|
log_debug("%s: lsr-id %s %s the Typed Wildcard FEC "
|
||||||
|
"capability", __func__, inet_ntoa(nbr->id),
|
||||||
|
(enable) ? "announced" : "withdrew");
|
||||||
|
break;
|
||||||
case TLV_TYPE_DYNAMIC_CAP:
|
case TLV_TYPE_DYNAMIC_CAP:
|
||||||
/*
|
/*
|
||||||
* RFC 5561 - Section 9:
|
* RFC 5561 - Section 9:
|
||||||
@ -305,3 +357,17 @@ gen_cap_dynamic_tlv(struct ibuf *buf)
|
|||||||
|
|
||||||
return (ibuf_add(buf, &cap, CAP_TLV_DYNAMIC_SIZE));
|
return (ibuf_add(buf, &cap, CAP_TLV_DYNAMIC_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
gen_cap_twcard_tlv(struct ibuf *buf, int enable)
|
||||||
|
{
|
||||||
|
struct capability_tlv cap;
|
||||||
|
|
||||||
|
memset(&cap, 0, sizeof(cap));
|
||||||
|
cap.type = htons(TLV_TYPE_TWCARD_CAP);
|
||||||
|
cap.length = htons(CAP_TLV_TWCARD_LEN);
|
||||||
|
if (enable)
|
||||||
|
cap.reserved = STATE_BIT;
|
||||||
|
|
||||||
|
return (ibuf_add(buf, &cap, CAP_TLV_TWCARD_SIZE));
|
||||||
|
}
|
||||||
|
@ -90,6 +90,16 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
|
|||||||
if (me->map.flags & F_MAP_PW_STATUS)
|
if (me->map.flags & F_MAP_PW_STATUS)
|
||||||
msg_size += PW_STATUS_TLV_SIZE;
|
msg_size += PW_STATUS_TLV_SIZE;
|
||||||
break;
|
break;
|
||||||
|
case MAP_TYPE_TYPED_WCARD:
|
||||||
|
msg_size += FEC_ELM_TWCARD_MIN_LEN;
|
||||||
|
switch (me->map.fec.twcard.type) {
|
||||||
|
case MAP_TYPE_PREFIX:
|
||||||
|
msg_size += sizeof(uint16_t);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatalx("send_labelmessage: unexpected fec type");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (me->map.label != NO_LABEL)
|
if (me->map.label != NO_LABEL)
|
||||||
msg_size += LABEL_TLV_SIZE;
|
msg_size += LABEL_TLV_SIZE;
|
||||||
@ -208,6 +218,24 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RFC 5561 - Section 4:
|
||||||
|
* "An LDP implementation that supports the Typed Wildcard
|
||||||
|
* FEC Element MUST support its use in Label Request, Label
|
||||||
|
* Withdraw, and Label Release messages".
|
||||||
|
*/
|
||||||
|
if (map.type == MAP_TYPE_TYPED_WCARD) {
|
||||||
|
switch (type) {
|
||||||
|
case MSG_TYPE_LABELMAPPING:
|
||||||
|
case MSG_TYPE_LABELABORTREQ:
|
||||||
|
session_shutdown(nbr, S_UNKNOWN_FEC, msg.id,
|
||||||
|
msg.type);
|
||||||
|
goto err;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LDP supports the use of multiple FEC Elements per
|
* LDP supports the use of multiple FEC Elements per
|
||||||
* FEC for the Label Mapping message only.
|
* FEC for the Label Mapping message only.
|
||||||
@ -524,7 +552,7 @@ gen_fec_tlv(struct ibuf *buf, struct map *map)
|
|||||||
{
|
{
|
||||||
struct tlv ft;
|
struct tlv ft;
|
||||||
uint16_t family, len, pw_type, ifmtu;
|
uint16_t family, len, pw_type, ifmtu;
|
||||||
uint8_t pw_len = 0;
|
uint8_t pw_len = 0, twcard_len;
|
||||||
uint32_t group_id, pwid;
|
uint32_t group_id, pwid;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@ -594,6 +622,43 @@ gen_fec_tlv(struct ibuf *buf, struct map *map)
|
|||||||
err |= ibuf_add(buf, &ifmtu, sizeof(uint16_t));
|
err |= ibuf_add(buf, &ifmtu, sizeof(uint16_t));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MAP_TYPE_TYPED_WCARD:
|
||||||
|
len = FEC_ELM_TWCARD_MIN_LEN;
|
||||||
|
switch (map->fec.twcard.type) {
|
||||||
|
case MAP_TYPE_PREFIX:
|
||||||
|
len += sizeof(uint16_t);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatalx("gen_fec_tlv: unexpected fec type");
|
||||||
|
}
|
||||||
|
ft.length = htons(len);
|
||||||
|
err |= ibuf_add(buf, &ft, sizeof(ft));
|
||||||
|
err |= ibuf_add(buf, &map->type, sizeof(uint8_t));
|
||||||
|
err |= ibuf_add(buf, &map->fec.twcard.type, sizeof(uint8_t));
|
||||||
|
|
||||||
|
switch (map->fec.twcard.type) {
|
||||||
|
case MAP_TYPE_PREFIX:
|
||||||
|
twcard_len = sizeof(uint16_t);
|
||||||
|
err |= ibuf_add(buf, &twcard_len, sizeof(uint8_t));
|
||||||
|
|
||||||
|
switch (map->fec.twcard.u.prefix_af) {
|
||||||
|
case AF_INET:
|
||||||
|
family = htons(AF_IPV4);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
family = htons(AF_IPV6);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatalx("gen_fec_tlv: unknown af");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
err |= ibuf_add(buf, &family, sizeof(uint16_t));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatalx("gen_fec_tlv: unexpected fec type");
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -606,7 +671,7 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
|
|||||||
uint16_t len, struct map *map)
|
uint16_t len, struct map *map)
|
||||||
{
|
{
|
||||||
uint16_t off = 0;
|
uint16_t off = 0;
|
||||||
uint8_t pw_len;
|
uint8_t pw_len, twcard_len;
|
||||||
|
|
||||||
map->type = *buf;
|
map->type = *buf;
|
||||||
off += sizeof(uint8_t);
|
off += sizeof(uint8_t);
|
||||||
@ -750,6 +815,57 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf,
|
|||||||
pw_len -= stlv.length;
|
pw_len -= stlv.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (off);
|
||||||
|
case MAP_TYPE_TYPED_WCARD:
|
||||||
|
if (len < FEC_ELM_TWCARD_MIN_LEN) {
|
||||||
|
session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
|
||||||
|
msg->type);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&map->fec.twcard.type, buf + off, sizeof(uint8_t));
|
||||||
|
off += sizeof(uint8_t);
|
||||||
|
memcpy(&twcard_len, buf + off, sizeof(uint8_t));
|
||||||
|
off += sizeof(uint8_t);
|
||||||
|
if (len != FEC_ELM_TWCARD_MIN_LEN + twcard_len) {
|
||||||
|
session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
|
||||||
|
msg->type);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (map->fec.twcard.type) {
|
||||||
|
case MAP_TYPE_PREFIX:
|
||||||
|
if (twcard_len != sizeof(uint16_t)) {
|
||||||
|
session_shutdown(nbr, S_BAD_TLV_LEN, msg->id,
|
||||||
|
msg->type);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&map->fec.twcard.u.prefix_af, buf + off,
|
||||||
|
sizeof(uint16_t));
|
||||||
|
map->fec.twcard.u.prefix_af =
|
||||||
|
ntohs(map->fec.twcard.u.prefix_af);
|
||||||
|
off += sizeof(uint16_t);
|
||||||
|
|
||||||
|
switch (map->fec.twcard.u.prefix_af) {
|
||||||
|
case AF_IPV4:
|
||||||
|
map->fec.twcard.u.prefix_af = AF_INET;
|
||||||
|
break;
|
||||||
|
case AF_IPV6:
|
||||||
|
map->fec.twcard.u.prefix_af = AF_INET6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
session_shutdown(nbr, S_BAD_TLV_VAL, msg->id,
|
||||||
|
msg->type);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
send_notification(nbr->tcp, S_UNKNOWN_FEC, msg->id,
|
||||||
|
msg->type);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
return (off);
|
return (off);
|
||||||
default:
|
default:
|
||||||
send_notification(nbr->tcp, S_UNKNOWN_FEC, msg->id, msg->type);
|
send_notification(nbr->tcp, S_UNKNOWN_FEC, msg->id, msg->type);
|
||||||
|
14
ldpd/lde.c
14
ldpd/lde.c
@ -1003,6 +1003,20 @@ lde_send_labelwithdraw_wcard(struct lde_nbr *ln, uint32_t label)
|
|||||||
lde_send_labelwithdraw(ln, NULL, &wcard, NULL);
|
lde_send_labelwithdraw(ln, NULL, &wcard, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lde_send_labelwithdraw_twcard_prefix(struct lde_nbr *ln, uint16_t af,
|
||||||
|
uint32_t label)
|
||||||
|
{
|
||||||
|
struct map wcard;
|
||||||
|
|
||||||
|
memset(&wcard, 0, sizeof(wcard));
|
||||||
|
wcard.type = MAP_TYPE_TYPED_WCARD;
|
||||||
|
wcard.fec.twcard.type = MAP_TYPE_PREFIX;
|
||||||
|
wcard.fec.twcard.u.prefix_af = af;
|
||||||
|
wcard.label = label;
|
||||||
|
lde_send_labelwithdraw(ln, NULL, &wcard, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lde_send_labelwithdraw_pwid_wcard(struct lde_nbr *ln, uint16_t pw_type,
|
lde_send_labelwithdraw_pwid_wcard(struct lde_nbr *ln, uint16_t pw_type,
|
||||||
uint32_t group_id)
|
uint32_t group_id)
|
||||||
|
@ -145,6 +145,8 @@ void lde_send_labelmapping(struct lde_nbr *, struct fec_node *,
|
|||||||
void lde_send_labelwithdraw(struct lde_nbr *, struct fec_node *,
|
void lde_send_labelwithdraw(struct lde_nbr *, struct fec_node *,
|
||||||
struct map *, struct status_tlv *);
|
struct map *, struct status_tlv *);
|
||||||
void lde_send_labelwithdraw_wcard(struct lde_nbr *, uint32_t);
|
void lde_send_labelwithdraw_wcard(struct lde_nbr *, uint32_t);
|
||||||
|
void lde_send_labelwithdraw_twcard_prefix(struct lde_nbr *,
|
||||||
|
uint16_t, uint32_t);
|
||||||
void lde_send_labelwithdraw_pwid_wcard(struct lde_nbr *, uint16_t,
|
void lde_send_labelwithdraw_pwid_wcard(struct lde_nbr *, uint16_t,
|
||||||
uint32_t);
|
uint32_t);
|
||||||
void lde_send_labelrelease(struct lde_nbr *, struct fec_node *,
|
void lde_send_labelrelease(struct lde_nbr *, struct fec_node *,
|
||||||
@ -181,6 +183,7 @@ void lde_kernel_remove(struct fec *, int, union ldpd_addr *,
|
|||||||
void lde_kernel_update(struct fec *);
|
void lde_kernel_update(struct fec *);
|
||||||
void lde_check_mapping(struct map *, struct lde_nbr *);
|
void lde_check_mapping(struct map *, struct lde_nbr *);
|
||||||
void lde_check_request(struct map *, struct lde_nbr *);
|
void lde_check_request(struct map *, struct lde_nbr *);
|
||||||
|
void lde_check_request_wcard(struct map *, struct lde_nbr *);
|
||||||
void lde_check_release(struct map *, struct lde_nbr *);
|
void lde_check_release(struct map *, struct lde_nbr *);
|
||||||
void lde_check_release_wcard(struct map *, struct lde_nbr *);
|
void lde_check_release_wcard(struct map *, struct lde_nbr *);
|
||||||
void lde_check_withdraw(struct map *, struct lde_nbr *);
|
void lde_check_withdraw(struct map *, struct lde_nbr *);
|
||||||
|
@ -555,6 +555,12 @@ lde_check_request(struct map *map, struct lde_nbr *ln)
|
|||||||
struct fec_node *fn;
|
struct fec_node *fn;
|
||||||
struct fec_nh *fnh;
|
struct fec_nh *fnh;
|
||||||
|
|
||||||
|
/* wildcard label request */
|
||||||
|
if (map->type == MAP_TYPE_TYPED_WCARD) {
|
||||||
|
lde_check_request_wcard(map, ln);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* LRq.1: skip loop detection (not necessary) */
|
/* LRq.1: skip loop detection (not necessary) */
|
||||||
|
|
||||||
/* LRq.2: is there a next hop for fec? */
|
/* LRq.2: is there a next hop for fec? */
|
||||||
@ -605,6 +611,40 @@ lde_check_request(struct map *map, struct lde_nbr *ln)
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lde_check_request_wcard(struct map *map, struct lde_nbr *ln)
|
||||||
|
{
|
||||||
|
struct fec *f;
|
||||||
|
struct fec_node *fn;
|
||||||
|
struct lde_req *lre;
|
||||||
|
|
||||||
|
RB_FOREACH(f, fec_tree, &ft) {
|
||||||
|
fn = (struct fec_node *)f;
|
||||||
|
|
||||||
|
/* only a typed wildcard is possible here */
|
||||||
|
if (lde_wildcard_apply(map, &fn->fec, NULL) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* LRq.2: is there a next hop for fec? */
|
||||||
|
if (LIST_EMPTY(&fn->nexthops))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* LRq.6: first check if we have a pending request running */
|
||||||
|
lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec);
|
||||||
|
if (lre != NULL)
|
||||||
|
/* LRq.7: duplicate request */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* LRq.8: record label request */
|
||||||
|
lre = lde_req_add(ln, &fn->fec, 0);
|
||||||
|
if (lre != NULL)
|
||||||
|
lre->msg_id = ntohl(map->msg_id);
|
||||||
|
|
||||||
|
/* LRq.9: perform LSR label distribution */
|
||||||
|
lde_send_labelmapping(ln, fn, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lde_check_release(struct map *map, struct lde_nbr *ln)
|
lde_check_release(struct map *map, struct lde_nbr *ln)
|
||||||
{
|
{
|
||||||
@ -615,6 +655,7 @@ lde_check_release(struct map *map, struct lde_nbr *ln)
|
|||||||
|
|
||||||
/* wildcard label release */
|
/* wildcard label release */
|
||||||
if (map->type == MAP_TYPE_WILDCARD ||
|
if (map->type == MAP_TYPE_WILDCARD ||
|
||||||
|
map->type == MAP_TYPE_TYPED_WCARD ||
|
||||||
(map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
|
(map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
|
||||||
lde_check_release_wcard(map, ln);
|
lde_check_release_wcard(map, ln);
|
||||||
return;
|
return;
|
||||||
@ -690,6 +731,7 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln)
|
|||||||
|
|
||||||
/* wildcard label withdraw */
|
/* wildcard label withdraw */
|
||||||
if (map->type == MAP_TYPE_WILDCARD ||
|
if (map->type == MAP_TYPE_WILDCARD ||
|
||||||
|
map->type == MAP_TYPE_TYPED_WCARD ||
|
||||||
(map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
|
(map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
|
||||||
lde_check_withdraw_wcard(map, ln);
|
lde_check_withdraw_wcard(map, ln);
|
||||||
return;
|
return;
|
||||||
@ -793,6 +835,20 @@ lde_wildcard_apply(struct map *wcard, struct fec *fec, struct lde_map *me)
|
|||||||
case MAP_TYPE_WILDCARD:
|
case MAP_TYPE_WILDCARD:
|
||||||
/* full wildcard */
|
/* full wildcard */
|
||||||
return (1);
|
return (1);
|
||||||
|
case MAP_TYPE_TYPED_WCARD:
|
||||||
|
switch (wcard->fec.twcard.type) {
|
||||||
|
case MAP_TYPE_PREFIX:
|
||||||
|
if (wcard->fec.twcard.u.prefix_af == AF_INET &&
|
||||||
|
fec->type != FEC_TYPE_IPV4)
|
||||||
|
return (0);
|
||||||
|
if (wcard->fec.twcard.u.prefix_af == AF_INET6 &&
|
||||||
|
fec->type != FEC_TYPE_IPV6)
|
||||||
|
return (0);
|
||||||
|
return (1);
|
||||||
|
default:
|
||||||
|
fatalx("lde_wildcard_apply: unexpected fec type");
|
||||||
|
}
|
||||||
|
break;
|
||||||
case MAP_TYPE_PWID:
|
case MAP_TYPE_PWID:
|
||||||
/* RFC4447 pw-id group wildcard */
|
/* RFC4447 pw-id group wildcard */
|
||||||
if (fec->type != FEC_TYPE_PWID)
|
if (fec->type != FEC_TYPE_PWID)
|
||||||
|
@ -99,6 +99,8 @@
|
|||||||
/* RFC 5561 */
|
/* RFC 5561 */
|
||||||
#define TLV_TYPE_RETURNED_TLVS 0x8304
|
#define TLV_TYPE_RETURNED_TLVS 0x8304
|
||||||
#define TLV_TYPE_DYNAMIC_CAP 0x8506
|
#define TLV_TYPE_DYNAMIC_CAP 0x8506
|
||||||
|
/* RFC 5918 */
|
||||||
|
#define TLV_TYPE_TWCARD_CAP 0x850B
|
||||||
/* RFC 7552 */
|
/* RFC 7552 */
|
||||||
#define TLV_TYPE_DUALSTACK 0x8701
|
#define TLV_TYPE_DUALSTACK 0x8701
|
||||||
|
|
||||||
@ -241,10 +243,14 @@ struct capability_tlv {
|
|||||||
#define STATE_BIT 0x80
|
#define STATE_BIT 0x80
|
||||||
|
|
||||||
#define F_CAP_TLV_RCVD_DYNAMIC 0x01
|
#define F_CAP_TLV_RCVD_DYNAMIC 0x01
|
||||||
|
#define F_CAP_TLV_RCVD_TWCARD 0x02
|
||||||
|
|
||||||
#define CAP_TLV_DYNAMIC_SIZE 5
|
#define CAP_TLV_DYNAMIC_SIZE 5
|
||||||
#define CAP_TLV_DYNAMIC_LEN 1
|
#define CAP_TLV_DYNAMIC_LEN 1
|
||||||
|
|
||||||
|
#define CAP_TLV_TWCARD_SIZE 5
|
||||||
|
#define CAP_TLV_TWCARD_LEN 1
|
||||||
|
|
||||||
#define AF_IPV4 0x1
|
#define AF_IPV4 0x1
|
||||||
#define AF_IPV6 0x2
|
#define AF_IPV6 0x2
|
||||||
|
|
||||||
@ -261,9 +267,11 @@ struct address_list_tlv {
|
|||||||
#define FEC_ELM_PREFIX_MIN_LEN 4
|
#define FEC_ELM_PREFIX_MIN_LEN 4
|
||||||
#define FEC_PWID_ELM_MIN_LEN 8
|
#define FEC_PWID_ELM_MIN_LEN 8
|
||||||
#define FEC_PWID_SIZE 4
|
#define FEC_PWID_SIZE 4
|
||||||
|
#define FEC_ELM_TWCARD_MIN_LEN 3
|
||||||
|
|
||||||
#define MAP_TYPE_WILDCARD 0x01
|
#define MAP_TYPE_WILDCARD 0x01
|
||||||
#define MAP_TYPE_PREFIX 0x02
|
#define MAP_TYPE_PREFIX 0x02
|
||||||
|
#define MAP_TYPE_TYPED_WCARD 0x05
|
||||||
#define MAP_TYPE_PWID 0x80
|
#define MAP_TYPE_PWID 0x80
|
||||||
#define MAP_TYPE_GENPWID 0x81
|
#define MAP_TYPE_GENPWID 0x81
|
||||||
|
|
||||||
|
@ -220,6 +220,12 @@ struct map {
|
|||||||
uint32_t group_id;
|
uint32_t group_id;
|
||||||
uint16_t ifmtu;
|
uint16_t ifmtu;
|
||||||
} pwid;
|
} pwid;
|
||||||
|
struct {
|
||||||
|
uint8_t type;
|
||||||
|
union {
|
||||||
|
uint16_t prefix_af;
|
||||||
|
} u;
|
||||||
|
} twcard;
|
||||||
} fec;
|
} fec;
|
||||||
struct {
|
struct {
|
||||||
uint32_t status_code;
|
uint32_t status_code;
|
||||||
|
@ -112,6 +112,7 @@ struct nbr {
|
|||||||
};
|
};
|
||||||
#define F_NBR_GTSM_NEGOTIATED 0x01
|
#define F_NBR_GTSM_NEGOTIATED 0x01
|
||||||
#define F_NBR_CAP_DYNAMIC 0x02
|
#define F_NBR_CAP_DYNAMIC 0x02
|
||||||
|
#define F_NBR_CAP_TWCARD 0x04
|
||||||
|
|
||||||
RB_HEAD(nbr_id_head, nbr);
|
RB_HEAD(nbr_id_head, nbr);
|
||||||
RB_PROTOTYPE(nbr_id_head, nbr, id_tree, nbr_id_compare)
|
RB_PROTOTYPE(nbr_id_head, nbr, id_tree, nbr_id_compare)
|
||||||
|
17
ldpd/log.c
17
ldpd/log.c
@ -332,6 +332,23 @@ log_map(const struct map *map)
|
|||||||
pw_type_name(map->fec.pwid.type)) == -1)
|
pw_type_name(map->fec.pwid.type)) == -1)
|
||||||
return ("???");
|
return ("???");
|
||||||
break;
|
break;
|
||||||
|
case MAP_TYPE_TYPED_WCARD:
|
||||||
|
if (snprintf(buf, sizeof(buf), "typed wildcard") < 0)
|
||||||
|
return ("???");
|
||||||
|
switch (map->fec.twcard.type) {
|
||||||
|
case MAP_TYPE_PREFIX:
|
||||||
|
if (snprintf(buf + strlen(buf), sizeof(buf) -
|
||||||
|
strlen(buf), " (prefix, address-family %s)",
|
||||||
|
af_name(map->fec.twcard.u.prefix_af)) < 0)
|
||||||
|
return ("???");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (snprintf(buf + strlen(buf), sizeof(buf) -
|
||||||
|
strlen(buf), " (unknown type)") < 0)
|
||||||
|
return ("???");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return ("???");
|
return ("???");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user