summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ldpd/labelmapping.c60
-rw-r--r--usr.sbin/ldpd/lde.c165
-rw-r--r--usr.sbin/ldpd/lde.h21
-rw-r--r--usr.sbin/ldpd/lde_lib.c398
-rw-r--r--usr.sbin/ldpd/ldp.h5
-rw-r--r--usr.sbin/ldpd/ldpd.h9
-rw-r--r--usr.sbin/ldpd/ldpe.c11
-rw-r--r--usr.sbin/ldpd/log.c5
8 files changed, 408 insertions, 266 deletions
diff --git a/usr.sbin/ldpd/labelmapping.c b/usr.sbin/ldpd/labelmapping.c
index 1322e481197..df62ce14e44 100644
--- a/usr.sbin/ldpd/labelmapping.c
+++ b/usr.sbin/ldpd/labelmapping.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: labelmapping.c,v 1.31 2015/02/09 11:53:25 claudio Exp $ */
+/* $OpenBSD: labelmapping.c,v 1.32 2015/07/19 20:54:16 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -41,6 +41,7 @@
void gen_label_tlv(struct ibuf *, u_int32_t);
void gen_reqid_tlv(struct ibuf *, u_int32_t);
void gen_fec_tlv(struct ibuf *, struct in_addr, u_int8_t);
+void gen_wcard_fec_tlv(struct ibuf *);
int tlv_decode_label(struct nbr *, struct ldp_msg *, char *, u_int16_t,
u_int32_t *);
@@ -80,10 +81,13 @@ send_labelmessage(struct nbr *nbr, u_int16_t type, struct mapping_head *mh)
}
/* calculate size */
- tlv_size = LDP_MSG_LEN + TLV_HDR_LEN + FEC_ELM_MIN_LEN +
- PREFIX_SIZE(me->map.prefixlen);
- if (type == MSG_TYPE_LABELMAPPING ||
- me->map.flags & F_MAP_OPTLABEL)
+ tlv_size = LDP_MSG_LEN + TLV_HDR_LEN;
+ if (me->map.flags & F_MAP_WILDCARD)
+ tlv_size += FEC_ELM_WCARD_LEN;
+ else
+ tlv_size += FEC_ELM_PREFIX_MIN_LEN +
+ PREFIX_SIZE(me->map.prefixlen);
+ if (me->map.label != NO_LABEL)
tlv_size += LABEL_TLV_LEN;
if (me->map.flags & F_MAP_REQ_ID)
tlv_size += REQID_TLV_LEN;
@@ -99,9 +103,11 @@ send_labelmessage(struct nbr *nbr, u_int16_t type, struct mapping_head *mh)
/* append message and tlvs */
gen_msg_tlv(buf, type, tlv_size);
- gen_fec_tlv(buf, me->map.prefix, me->map.prefixlen);
- if (type == MSG_TYPE_LABELMAPPING ||
- me->map.flags & F_MAP_OPTLABEL)
+ if (me->map.flags & F_MAP_WILDCARD)
+ gen_wcard_fec_tlv(buf);
+ else
+ gen_fec_tlv(buf, me->map.prefix, me->map.prefixlen);
+ if (me->map.label != NO_LABEL)
gen_label_tlv(buf, me->map.label);
if (me->map.flags & F_MAP_REQ_ID)
gen_reqid_tlv(buf, me->map.requestid);
@@ -121,7 +127,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, u_int16_t len, u_int16_t type)
{
struct ldp_msg lm;
struct tlv ft;
- u_int32_t label, reqid = 0;
+ u_int32_t label = NO_LABEL, reqid = 0;
u_int8_t flags = 0;
int feclen, lbllen, tlen;
@@ -228,7 +234,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, u_int16_t len, u_int16_t type)
case TLV_TYPE_LABELREQUEST:
switch (type) {
case MSG_TYPE_LABELMAPPING:
- case MSG_TYPE_LABELABORTREQ:
+ case MSG_TYPE_LABELREQUEST:
if (ntohs(tlv.length) != 4) {
session_shutdown(nbr, S_BAD_TLV_LEN,
lm.msgid, lm.type);
@@ -260,7 +266,6 @@ recv_labelmessage(struct nbr *nbr, char *buf, u_int16_t len, u_int16_t type)
memcpy(&labelbuf, buf, sizeof(labelbuf));
label = ntohl(labelbuf);
- flags |= F_MAP_OPTLABEL;
break;
default:
/* ignore */
@@ -299,26 +304,35 @@ recv_labelmessage(struct nbr *nbr, char *buf, u_int16_t len, u_int16_t type)
int imsg_type = IMSG_NONE;
me->map.flags |= flags;
- if (type == MSG_TYPE_LABELMAPPING ||
- me->map.flags & F_MAP_OPTLABEL)
- me->map.label = label;
+ me->map.label = label;
if (me->map.flags & F_MAP_REQ_ID)
me->map.requestid = reqid;
switch (type) {
case MSG_TYPE_LABELMAPPING:
+ log_debug("label mapping from nbr %s, FEC %s, "
+ "label %u", inet_ntoa(nbr->id),
+ log_fec(&me->map), me->map.label);
imsg_type = IMSG_LABEL_MAPPING;
break;
case MSG_TYPE_LABELREQUEST:
+ log_debug("label request from nbr %s, FEC %s",
+ inet_ntoa(nbr->id), log_fec(&me->map));
imsg_type = IMSG_LABEL_REQUEST;
break;
case MSG_TYPE_LABELWITHDRAW:
+ log_debug("label withdraw from nbr %s, FEC %s",
+ inet_ntoa(nbr->id), log_fec(&me->map));
imsg_type = IMSG_LABEL_WITHDRAW;
break;
case MSG_TYPE_LABELRELEASE:
+ log_debug("label release from nbr %s, FEC %s",
+ inet_ntoa(nbr->id), log_fec(&me->map));
imsg_type = IMSG_LABEL_RELEASE;
break;
case MSG_TYPE_LABELABORTREQ:
+ log_debug("label abort from nbr %s, FEC %s",
+ inet_ntoa(nbr->id), log_fec(&me->map));
imsg_type = IMSG_LABEL_ABORT;
break;
default:
@@ -436,6 +450,20 @@ gen_fec_tlv(struct ibuf *buf, struct in_addr prefix, u_int8_t prefixlen)
ibuf_add(buf, &prefix, len);
}
+void
+gen_wcard_fec_tlv(struct ibuf *buf)
+{
+ struct tlv ft;
+ u_int8_t type;
+
+ ft.type = htons(TLV_TYPE_FEC);
+ ft.length = htons(sizeof(type));
+ ibuf_add(buf, &ft, sizeof(ft));
+
+ type = FEC_WILDCARD;
+ ibuf_add(buf, &type, sizeof(type));
+}
+
int
tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *lm, char *buf,
u_int16_t len, u_int8_t *type, u_int32_t *prefix, u_int8_t *prefixlen)
@@ -446,7 +474,7 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *lm, char *buf,
off += sizeof(u_int8_t);
if (*type == FEC_WILDCARD) {
- if (len == 0)
+ if (len == FEC_ELM_WCARD_LEN)
return (off);
else {
session_shutdown(nbr, S_BAD_TLV_VAL, lm->msgid,
@@ -460,7 +488,7 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *lm, char *buf,
return (-1);
}
- if (len < FEC_ELM_MIN_LEN) {
+ if (len < FEC_ELM_PREFIX_MIN_LEN) {
session_shutdown(nbr, S_BAD_TLV_LEN, lm->msgid, lm->type);
return (-1);
}
diff --git a/usr.sbin/ldpd/lde.c b/usr.sbin/ldpd/lde.c
index 354d6d6ad93..12ff6d9fe08 100644
--- a/usr.sbin/ldpd/lde.c
+++ b/usr.sbin/ldpd/lde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde.c,v 1.32 2015/07/19 20:50:03 renato Exp $ */
+/* $OpenBSD: lde.c,v 1.33 2015/07/19 20:54:16 renato Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -231,8 +231,6 @@ lde_dispatch_imsg(int fd, short event, void *bula)
}
rt_snap(nbr);
- lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END,
- imsg.hdr.peerid, 0, NULL, 0);
break;
case IMSG_LABEL_MAPPING:
case IMSG_LABEL_REQUEST:
@@ -258,14 +256,20 @@ lde_dispatch_imsg(int fd, short event, void *bula)
lde_check_request(&map, nbr);
break;
case IMSG_LABEL_RELEASE:
- lde_check_release(&map, nbr);
+ if (map.flags & F_MAP_WILDCARD)
+ lde_check_release_wcard(&map, nbr);
+ else
+ lde_check_release(&map, nbr);
break;
case IMSG_LABEL_WITHDRAW:
- lde_check_withdraw(&map, nbr);
+ if (map.flags & F_MAP_WILDCARD)
+ lde_check_withdraw_wcard(&map, nbr);
+ else
+ lde_check_withdraw(&map, nbr);
+ break;
+ case IMSG_LABEL_ABORT:
+ /* not necessary */
break;
- default:
- log_warnx("type %d not yet handled. nbr %s",
- imsg.hdr.type, inet_ntoa(nbr->id));
}
break;
case IMSG_ADDRESS_ADD:
@@ -467,31 +471,6 @@ lde_send_delete_klabel(struct rt_node *rr, struct rt_lsp *rl)
}
void
-lde_send_labelrequest(struct lde_nbr *ln, struct rt_node *rn)
-{
- struct map map;
-
- /* TODO check if status of peer is OK to send requests (SLRq.2 & 6)
- * For now assume no peer will send no-label-resource notifications */
-
- /* check if request is already pending */
- if (fec_find(&ln->sent_req, &rn->fec) != NULL)
- return;
- /* and try to add request to pending list */
- lde_req_add(ln, &rn->fec, 1);
- /* msgid does not matter since only one req can be pending */
-
- bzero(&map, sizeof(map));
- map.prefix = rn->fec.prefix;
- map.prefixlen = rn->fec.prefixlen;
-
- lde_imsg_compose_ldpe(IMSG_REQUEST_ADD, ln->peerid, 0,
- &map, sizeof(map));
- lde_imsg_compose_ldpe(IMSG_REQUEST_ADD_END, ln->peerid, 0,
- NULL, 0);
-}
-
-void
lde_send_labelmapping(struct lde_nbr *ln, struct rt_node *rn)
{
struct lde_req *lre;
@@ -499,7 +478,7 @@ lde_send_labelmapping(struct lde_nbr *ln, struct rt_node *rn)
struct map map;
/*
- * This function skips SL.1 - 3 and SL.9 - 14 because the lable
+ * This function skips SL.1 - 3 and SL.9 - 14 because the label
* allocation is done way earlier (because of the merging nature of
* ldpd).
*/
@@ -509,24 +488,67 @@ lde_send_labelmapping(struct lde_nbr *ln, struct rt_node *rn)
map.prefix = rn->fec.prefix;
map.prefixlen = rn->fec.prefixlen;
- /* is there a pending request for this mapping? */
+ /* SL.6: is there a pending request for this mapping? */
lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec);
if (lre) {
/* set label request msg id in the mapping response. */
map.requestid = lre->msgid;
map.flags = F_MAP_REQ_ID;
+
+ /* SL.7: delete record of pending request */
lde_req_del(ln, lre, 0);
}
+ /* SL.4: send label mapping */
+ lde_imsg_compose_ldpe(IMSG_MAPPING_ADD, ln->peerid, 0,
+ &map, sizeof(map));
+
+ /* SL.5: record sent label mapping */
me = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec);
if (me == NULL)
me = lde_map_add(ln, rn, 1);
me->label = map.label;
+}
- lde_imsg_compose_ldpe(IMSG_MAPPING_ADD, ln->peerid, 0,
- &map, sizeof(map));
- lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0,
- NULL, 0);
+void
+lde_send_labelwithdraw(struct lde_nbr *ln, struct rt_node *rn)
+{
+ struct lde_wdraw *lw;
+ struct map map;
+ struct fec *f;
+
+ bzero(&map, sizeof(map));
+ if (rn) {
+ map.label = rn->local_label;
+ map.prefix = rn->fec.prefix;
+ map.prefixlen = rn->fec.prefixlen;
+ } else {
+ map.label = NO_LABEL;
+ map.flags = F_MAP_WILDCARD;
+ }
+
+ /* SWd.1: send label withdraw. */
+ lde_imsg_compose_ldpe(IMSG_WITHDRAW_ADD, ln->peerid, 0,
+ &map, sizeof(map));
+ lde_imsg_compose_ldpe(IMSG_WITHDRAW_ADD_END, ln->peerid, 0, NULL, 0);
+
+ /* SWd.2: record label withdraw. */
+ if (rn) {
+ lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &rn->fec);
+ if (lw == NULL)
+ lw = lde_wdraw_add(ln, rn);
+ lw->label = map.label;
+ } else {
+ RB_FOREACH(f, fec_tree, &rt) {
+ rn = (struct rt_node *)f;
+
+ lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw,
+ &rn->fec);
+ if (lw == NULL)
+ lw = lde_wdraw_add(ln, rn);
+ lw->label = map.label;
+ }
+ }
}
void
@@ -535,17 +557,16 @@ lde_send_labelrelease(struct lde_nbr *ln, struct rt_node *rn, u_int32_t label)
struct map map;
bzero(&map, sizeof(map));
- map.prefix = rn->fec.prefix;
- map.prefixlen = rn->fec.prefixlen;
- if (label != NO_LABEL) {
- map.flags = F_MAP_OPTLABEL;
- map.label = label;
- }
+ if (rn) {
+ map.prefix = rn->fec.prefix;
+ map.prefixlen = rn->fec.prefixlen;
+ } else
+ map.flags = F_MAP_WILDCARD;
+ map.label = label;
lde_imsg_compose_ldpe(IMSG_RELEASE_ADD, ln->peerid, 0,
&map, sizeof(map));
- lde_imsg_compose_ldpe(IMSG_RELEASE_ADD_END, ln->peerid, 0,
- NULL, 0);
+ lde_imsg_compose_ldpe(IMSG_RELEASE_ADD_END, ln->peerid, 0, NULL, 0);
}
void
@@ -657,31 +678,6 @@ lde_nbr_clear(void)
lde_nbr_del(nbr);
}
-void
-lde_nbr_do_mappings(struct rt_node *rn)
-{
- struct lde_nbr *ln;
- struct lde_map *me;
- struct lde_req *lre;
-
- /* This handles LMp.17-31 for lde_check_mapping() */
-
- RB_FOREACH(ln, nbr_tree, &lde_nbrs) {
- /* LMp.18 Did we already send a mapping to this peer? */
- me = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec);
- if (me && me->label == rn->local_label)
- /* same mapping already sent, skip */
- /* TODO LMp.22-27 Loop detection check */
- continue;
-
- /* LMp.28 Is this from a pending request? */
- lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec);
-
- lde_send_labelmapping(ln, rn);
- /* LMp.30 & 31 are not needed because labels are always added */
- }
-}
-
struct lde_map *
lde_map_add(struct lde_nbr *ln, struct rt_node *rn, int sent)
{
@@ -765,6 +761,31 @@ lde_req_del(struct lde_nbr *ln, struct lde_req *lre, int sent)
free(lre);
}
+struct lde_wdraw *
+lde_wdraw_add(struct lde_nbr *ln, struct rt_node *rn)
+{
+ struct lde_wdraw *lw;
+
+ lw = calloc(1, sizeof(*lw));
+ if (lw == NULL)
+ fatal("lde_wdraw_add");
+
+ lw->fec = rn->fec;
+
+ if (fec_insert(&ln->sent_wdraw, &lw->fec))
+ log_warnx("failed to add %s/%u to sent wdraw",
+ inet_ntoa(lw->fec.prefix), lw->fec.prefixlen);
+
+ return (lw);
+}
+
+void
+lde_wdraw_del(struct lde_nbr *ln, struct lde_wdraw *lw)
+{
+ fec_remove(&ln->sent_wdraw, &lw->fec);
+ free(lw);
+}
+
int
lde_address_add(struct lde_nbr *lr, struct in_addr *addr)
{
diff --git a/usr.sbin/ldpd/lde.h b/usr.sbin/ldpd/lde.h
index c7a072ba8d7..4bdbd7fa365 100644
--- a/usr.sbin/ldpd/lde.h
+++ b/usr.sbin/ldpd/lde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde.h,v 1.25 2015/07/19 18:34:32 renato Exp $ */
+/* $OpenBSD: lde.h,v 1.26 2015/07/19 20:54:16 renato Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -36,11 +36,7 @@ struct fec {
RB_PROTOTYPE(fec_tree, fec, entry, fec_compare)
extern struct fec_tree rt;
-/*
- * fec tree of pending label request
- * Note: currently only one outstanding request per FEC can be tracked but
- * should not be a problem since ldpd does not support multipath for now.
- */
+/* request entries */
struct lde_req {
struct fec fec;
u_int32_t msgid;
@@ -54,6 +50,12 @@ struct lde_map {
u_int32_t label;
};
+/* withdraw entries */
+struct lde_wdraw {
+ struct fec fec;
+ u_int32_t label;
+};
+
/* Addresses belonging to neighbor */
struct lde_nbr_address {
TAILQ_ENTRY(lde_nbr_address) entry;
@@ -102,15 +104,16 @@ u_int32_t lde_assign_label(void);
void lde_send_change_klabel(struct rt_node *, struct rt_lsp *);
void lde_send_delete_klabel(struct rt_node *, struct rt_lsp *);
void lde_send_labelmapping(struct lde_nbr *, struct rt_node *);
-void lde_send_labelrequest(struct lde_nbr *, struct rt_node *);
+void lde_send_labelwithdraw(struct lde_nbr *, struct rt_node *);
void lde_send_labelrelease(struct lde_nbr *, struct rt_node *, u_int32_t);
void lde_send_notification(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
-void lde_nbr_do_mappings(struct rt_node *);
struct lde_map *lde_map_add(struct lde_nbr *, struct rt_node *, int);
void lde_map_del(struct lde_nbr *, struct lde_map *, int);
struct lde_req *lde_req_add(struct lde_nbr *, struct fec *, int);
void lde_req_del(struct lde_nbr *, struct lde_req *, int);
+struct lde_wdraw *lde_wdraw_add(struct lde_nbr *, struct rt_node *);
+void lde_wdraw_del(struct lde_nbr *, struct lde_wdraw *);
struct lde_nbr *lde_find_address(struct in_addr);
int lde_address_add(struct lde_nbr *, struct in_addr *);
@@ -134,7 +137,9 @@ void lde_kernel_remove(struct kroute *);
void lde_check_mapping(struct map *, struct lde_nbr *);
void lde_check_request(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_withdraw(struct map *, struct lde_nbr *);
+void lde_check_withdraw_wcard(struct map *, struct lde_nbr *);
void lde_label_list_free(struct lde_nbr *);
#endif /* _LDE_H_ */
diff --git a/usr.sbin/ldpd/lde_lib.c b/usr.sbin/ldpd/lde_lib.c
index 2977a6171eb..90dda85c783 100644
--- a/usr.sbin/ldpd/lde_lib.c
+++ b/usr.sbin/ldpd/lde_lib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde_lib.c,v 1.36 2015/07/19 20:50:03 renato Exp $ */
+/* $OpenBSD: lde_lib.c,v 1.37 2015/07/19 20:54:16 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -49,6 +49,9 @@ int lde_nbr_is_nexthop(struct rt_node *, struct lde_nbr *);
RB_GENERATE(fec_tree, fec, entry, fec_compare)
+extern struct nbr_tree lde_nbrs;
+RB_PROTOTYPE(nbr_tree, lde_nbr, entry, lde_nbr_compare)
+
extern struct ldpd_conf *ldeconf;
struct fec_tree rt = RB_INITIALIZER(&rt);
@@ -145,6 +148,10 @@ rt_dump(pid_t pid)
RB_FOREACH(f, fec_tree, &rt) {
rr = (struct rt_node *)f;
+ if (rr->local_label == NO_LABEL &&
+ LIST_EMPTY(&rr->downstream))
+ continue;
+
rtctl.prefix = rr->fec.prefix;
rtctl.prefixlen = rr->fec.prefixlen;
rtctl.flags = rr->flags;
@@ -173,23 +180,20 @@ void
rt_snap(struct lde_nbr *ln)
{
struct fec *f;
- struct rt_node *r;
- struct lde_map *me;
- struct map map;
+ struct rt_node *rn;
+ int count = 0;
- bzero(&map, sizeof(map));
RB_FOREACH(f, fec_tree, &rt) {
- r = (struct rt_node *)f;
- map.prefix = r->fec.prefix;
- map.prefixlen = r->fec.prefixlen;
- map.label = r->local_label;
-
- me = lde_map_add(ln, r, 1);
- me->label = r->local_label;
+ rn = (struct rt_node *)f;
+ if (rn->local_label == NO_LABEL)
+ continue;
- lde_imsg_compose_ldpe(IMSG_MAPPING_ADD, ln->peerid, 0, &map,
- sizeof(map));
+ lde_send_labelmapping(ln, rn);
+ count++;
}
+ if (count > 0)
+ lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END,
+ ln->peerid, 0, NULL, 0);
}
void
@@ -198,11 +202,8 @@ rt_free(void *arg)
struct rt_node *rr = arg;
struct rt_lsp *rl;
- while ((rl = LIST_FIRST(&rr->lsp))) {
- LIST_REMOVE(rl, entry);
- free(rl);
- }
-
+ while ((rl = LIST_FIRST(&rr->lsp)))
+ rt_lsp_del(rl);
if (!LIST_EMPTY(&rr->downstream))
log_warnx("rt_free: fec %s/%u downstream list not empty",
inet_ntoa(rr->fec.prefix), rr->fec.prefixlen);
@@ -210,7 +211,7 @@ rt_free(void *arg)
log_warnx("rt_free: fec %s/%u upstream list not empty",
inet_ntoa(rr->fec.prefix), rr->fec.prefixlen);
- free(rl);
+ free(rr);
}
void
@@ -281,47 +282,74 @@ lde_kernel_insert(struct kroute *kr)
{
struct rt_node *rn;
struct rt_lsp *rl;
- struct lde_nbr_address *addr;
- struct lde_map *map;
+ struct lde_map *me;
+ struct lde_nbr *ln;
+ char buf[16];
- log_debug("kernel add route %s/%u", inet_ntoa(kr->prefix),
- kr->prefixlen);
+ log_debug("kernel add route %s/%u nexthop %s",
+ inet_ntoa(kr->prefix), kr->prefixlen,
+ inet_ntop(AF_INET, &kr->nexthop, buf, sizeof(buf)));
rn = (struct rt_node *)fec_find_prefix(&rt, kr->prefix.s_addr,
kr->prefixlen);
if (rn == NULL)
rn = rt_add(kr->prefix, kr->prefixlen);
- rl = rt_lsp_find(rn, kr->nexthop);
- if (rl == NULL)
- rl = rt_lsp_add(rn, kr->nexthop);
-
- /* There is static assigned label for this route, record it in lib */
- if (kr->local_label != NO_LABEL) {
- rn->local_label = kr->local_label;
+ if (rt_lsp_find(rn, kr->nexthop) != NULL)
return;
- }
- if (rn->local_label == NO_LABEL) {
- if (kr->flags & F_CONNECTED)
- /* Directly connected route */
- rn->local_label = MPLS_LABEL_IMPLNULL;
- else
- rn->local_label = lde_assign_label();
- }
+ if (LIST_EMPTY(&rn->lsp)) {
+ if (rn->local_label == NO_LABEL) {
+ if (kr->flags & F_CONNECTED)
+ rn->local_label = MPLS_LABEL_IMPLNULL;
+ else
+ rn->local_label = lde_assign_label();
+ } else {
+ /* Handle local label changes */
+ if ((kr->flags & F_CONNECTED) &&
+ rn->local_label != MPLS_LABEL_IMPLNULL) {
+ /* explicit withdraw of the previous label */
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs)
+ lde_send_labelwithdraw(ln, rn);
+ rn->local_label = MPLS_LABEL_IMPLNULL;
+ }
+
+ if (!(kr->flags & F_CONNECTED) &&
+ rn->local_label == MPLS_LABEL_IMPLNULL) {
+ /* explicit withdraw of the previous label */
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs)
+ lde_send_labelwithdraw(ln, rn);
+ rn->local_label = lde_assign_label();
+ }
+ }
- LIST_FOREACH(map, &rn->downstream, entry) {
- addr = lde_address_find(map->nexthop, &rl->nexthop);
- if (addr != NULL) {
- rl->remote_label = map->label;
- break;
+ /* FEC.1: perform lsr label distribution procedure */
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs) {
+ lde_send_labelmapping(ln, rn);
+ lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END,
+ ln->peerid, 0, NULL, 0);
}
}
+ rl = rt_lsp_add(rn, kr->nexthop);
lde_send_change_klabel(rn, rl);
- /* Redistribute the current mapping to every nbr */
- lde_nbr_do_mappings(rn);
+ ln = lde_find_address(rl->nexthop);
+ if (ln) {
+ /* FEC.2 */
+ me = (struct lde_map *)fec_find(&ln->recv_map, &rn->fec);
+ if (me) {
+ struct map map;
+
+ bzero(&map, sizeof(map));
+ map.prefix.s_addr = me->fec.prefix.s_addr;
+ map.prefixlen = me->fec.prefixlen;
+ map.label = me->label;
+
+ /* FEC.5 */
+ lde_check_mapping(&map, ln);
+ }
+ }
}
void
@@ -329,9 +357,12 @@ lde_kernel_remove(struct kroute *kr)
{
struct rt_node *rn;
struct rt_lsp *rl;
+ struct lde_nbr *ln;
+ char buf[16];
- log_debug("kernel remove route %s/%u", inet_ntoa(kr->prefix),
- kr->prefixlen);
+ log_debug("kernel remove route %s/%u nexthop %s",
+ inet_ntoa(kr->prefix), kr->prefixlen,
+ inet_ntop(AF_INET, &kr->nexthop, buf, sizeof(buf)));
rn = (struct rt_node *)fec_find_prefix(&rt, kr->prefix.s_addr,
kr->prefixlen);
@@ -340,13 +371,14 @@ lde_kernel_remove(struct kroute *kr)
return;
rl = rt_lsp_find(rn, kr->nexthop);
- if (rl != NULL)
- rt_lsp_del(rl);
-
- /* XXX handling of total loss of route, withdraw mappings, etc */
+ if (rl == NULL)
+ /* route lost */
+ return;
- /* Redistribute the current mapping to every nbr */
- lde_nbr_do_mappings(rn);
+ rt_lsp_del(rl);
+ if (LIST_EMPTY(&rn->lsp))
+ RB_FOREACH(ln, nbr_tree, &lde_nbrs)
+ lde_send_labelwithdraw(ln, rn);
}
void
@@ -355,76 +387,76 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln)
struct rt_node *rn;
struct rt_lsp *rl;
struct lde_req *lre;
- struct lde_nbr_address *addr = NULL;
+ struct lde_nbr_address *addr;
struct lde_map *me;
-
- log_debug("label mapping from nbr %s, FEC %s, label %u",
- inet_ntoa(ln->id), log_fec(map), map->label);
+ int msgsource = 0;
rn = (struct rt_node *)fec_find_prefix(&rt, map->prefix.s_addr,
map->prefixlen);
- if (rn == NULL) {
+ if (rn == NULL)
rn = rt_add(map->prefix, map->prefixlen);
- rn->local_label = lde_assign_label();
- }
- /* first check if we have a pending request running */
+ /* LMp.1: first check if we have a pending request running */
lre = (struct lde_req *)fec_find(&ln->sent_req, &rn->fec);
if (lre)
+ /* LMp.2: delete record of outstanding label request */
lde_req_del(ln, lre, 1);
- /* TODO Loop detection LMp.3 - LMp.8 */
+ /*
+ * LMp.3 - LMp.8: Loop detection LMp.3 - unecessary for frame-mode
+ * mpls networks
+ */
- LIST_FOREACH(me, &rn->downstream, entry) {
- if (ln != me->nexthop) /* LMp.9 */
- continue;
- if (lre)
- /* LMp.10 Note 6: req. mappings are always new */
- break;
- if (me->label != map->label) { /* LMp.10 */
- /*
- * This is, according to the RFC, a try to install a
- * multipath LSP which is not supported by the RFC.
- * So instead release the old label and install the
- * new one.
- */
- log_debug("possible multipath FEC %s, "
- "label %u, old label %u",
- log_fec(map), map->label, me->label);
+ /* LMp.9 */
+ me = (struct lde_map *)fec_find(&ln->recv_map, &rn->fec);
+ if (me) {
+ /* LMp.10 */
+ if (me->label != map->label && lre == NULL) {
+ /* LMp.10a */
lde_send_labelrelease(ln, rn, me->label);
+
+ LIST_FOREACH(rl, &rn->lsp, entry)
+ TAILQ_FOREACH(addr, &ln->addr_list, entry)
+ if (rl->nexthop.s_addr ==
+ addr->addr.s_addr) {
+ lde_send_delete_klabel(rn, rl);
+ rl->remote_label = NO_LABEL;
+ }
}
- /* there can only be one mapping */
- break;
}
- /* LMp.11: get nexthop */
+ /*
+ * LMp.11 - 12: consider multiple nexthops in order to
+ * support multipath
+ */
LIST_FOREACH(rl, &rn->lsp, entry) {
- addr = lde_address_find(ln, &rl->nexthop);
- if (addr)
- break;
+ if (lde_address_find(ln, &rl->nexthop)) {
+ msgsource = 1;
+
+ /* LMp.15: install FEC in FIB */
+ rl->remote_label = map->label;
+ lde_send_change_klabel(rn, rl);
+ }
}
- if (addr == NULL) {
- /* in liberal mode just note the mapping */
+ if (msgsource == 0) {
+ /* LMp.13: perform lsr label release procedure */
if (me == NULL)
me = lde_map_add(ln, rn, 0);
me->label = map->label;
-
return;
}
- /* LMp.14 do we actually need this FEC for now this is always true */
- rl->remote_label = map->label;
-
- /* LMp.15 install FEC in FIB */
- lde_send_change_klabel(rn, rl);
-
- /* Record the mapping from this peer LMp.16 */
+ /* LMp.16: Record the mapping from this peer */
if (me == NULL)
me = lde_map_add(ln, rn, 0);
me->label = map->label;
- /* Redistribute the current mapping to every nbr LMp.17-31 */
- lde_nbr_do_mappings(rn);
+
+ /*
+ * LMp.17 - LMp.27 are unnecessary since we don't need to implement
+ * loop detection. LMp.28 - LMp.30 are unnecessary because we are
+ * merging capable.
+ */
}
void
@@ -433,91 +465,112 @@ lde_check_request(struct map *map, struct lde_nbr *ln)
struct lde_req *lre;
struct rt_node *rn;
struct rt_lsp *rl;
- struct lde_nbr *lnn;
- log_debug("label request from nbr %s, FEC %s",
- inet_ntoa(ln->id), log_fec(map));
+ /* TODO LRq.1: loop detection */
+ /* LRq.2: is there a next hop for fec? */
rn = (struct rt_node *)fec_find_prefix(&rt, map->prefix.s_addr,
map->prefixlen);
- if (rn == NULL) {
+ if (rn == NULL || LIST_EMPTY(&rn->lsp)) {
lde_send_notification(ln->peerid, S_NO_ROUTE, map->messageid,
MSG_TYPE_LABELREQUEST);
return;
}
+ /* LRq.3: is MsgSource the next hop? */
LIST_FOREACH(rl, &rn->lsp, entry) {
if (lde_address_find(ln, &rl->nexthop)) {
lde_send_notification(ln->peerid, S_LOOP_DETECTED,
map->messageid, MSG_TYPE_LABELREQUEST);
return;
}
-
- if (rl->remote_label != NO_LABEL)
- break;
}
- /* first check if we have a pending request running */
+ /* LRq.6: first check if we have a pending request running */
lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec);
if (lre != NULL)
+ /* LRq.7: duplicate request */
return;
- /* else record label request */
+
+ /* LRq.8: record label request */
lre = lde_req_add(ln, &rn->fec, 0);
if (lre != NULL)
lre->msgid = map->messageid;
- /* there is a valid mapping available */
- if (rl != NULL) {
- /* TODO loop protection handling (LRq.9) */
- lde_send_labelmapping(ln, rn);
- return;
- }
+ /* LRq.9: perform LSR label distribution */
+ lde_send_labelmapping(ln, rn);
+ lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0, NULL, 0);
- /* no mapping available, try to request */
- /* XXX depending on the request behaviour we could return here */
- LIST_FOREACH(rl, &rn->lsp, entry) {
- lnn = lde_find_address(rl->nexthop);
- if (lnn == NULL)
- continue;
- lde_send_labelrequest(lnn, rn);
- }
+ /*
+ * LRq.10: do nothing (Request Never) since we use liberal
+ * label retention.
+ * LRq.11 - 12 are unnecessary since we are merging capable.
+ */
}
void
lde_check_release(struct map *map, struct lde_nbr *ln)
{
- struct rt_node *rn;
- struct lde_req *lre;
- struct lde_map *me;
-
- log_debug("label release from nbr %s, FEC %s",
- inet_ntoa(ln->id), log_fec(map));
+ struct rt_node *rn;
+ struct lde_wdraw *lw;
+ struct lde_map *me;
rn = (struct rt_node *)fec_find_prefix(&rt, map->prefix.s_addr,
map->prefixlen);
+ /* LRl.1: does FEC match a known FEC? */
if (rn == NULL)
return;
- /* first check if we have a pending withdraw running */
- lre = (struct lde_req *)fec_find(&ln->sent_wdraw, &rn->fec);
- if (lre) {
- fec_remove(&ln->sent_wdraw, &lre->fec);
- free(lre);
+ /* LRl.3: first check if we have a pending withdraw running */
+ lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &rn->fec);
+ if (lw && (map->label == NO_LABEL ||
+ (lw->label != NO_LABEL && map->label == lw->label))) {
+ /* LRl.4: delete record of outstanding label withdraw */
+ lde_wdraw_del(ln, lw);
}
- /* check sent map list and remove it if available */
+ /* LRl.6: check sent map list and remove it if available */
me = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec);
- if (me)
+ if (me && (map->label == NO_LABEL || map->label == me->label))
lde_map_del(ln, me, 1);
- /* remove FEC if not in use anymore */
- /* XXX what about outstanding label requests? */
- if (!LIST_EMPTY(&rn->upstream))
- return;
+ /*
+ * LRl.11 - 13 are unnecessary since we remove the label from
+ * forwarding/switching as soon as the FEC is unreachable.
+ */
+}
+
+void
+lde_check_release_wcard(struct map *map, struct lde_nbr *ln)
+{
+ struct fec *f;
+ struct rt_node *rn;
+ struct lde_wdraw *lw;
+ struct lde_map *me;
- /* XXX if originated here free all resources */
- /* else decide if a label release should be forwarded. */
- /* Since we do liberal retention we can keep the path mapped. */
+ RB_FOREACH(f, fec_tree, &rt) {
+ rn = (struct rt_node *)f;
+
+ /* LRl.3: first check if we have a pending withdraw running */
+ lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &rn->fec);
+ if (lw && (map->label == NO_LABEL ||
+ (lw->label != NO_LABEL && map->label == lw->label))) {
+ /* LRl.4: delete record of outstanding lbl withdraw */
+ lde_wdraw_del(ln, lw);
+ }
+
+ /* LRl.6: check sent map list and remove it if available */
+ me = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec);
+ if (me &&
+ (map->label == NO_LABEL || map->label == me->label)) {
+ lde_map_del(ln, me, 1);
+ }
+
+ /*
+ * LRl.11 - 13 are unnecessary since we remove the label from
+ * forwarding/switching as soon as the FEC is unreachable.
+ */
+ }
}
void
@@ -527,37 +580,58 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln)
struct rt_lsp *rl;
struct lde_map *me;
- log_debug("label withdraw from nbr %s, FEC %s",
- inet_ntoa(ln->id), log_fec(map));
-
rn = (struct rt_node *)fec_find_prefix(&rt, map->prefix.s_addr,
map->prefixlen);
-
- lde_send_labelrelease(ln, rn, map->label);
-
if (rn == NULL)
- /* LSP not available, nothing to do */
- return;
+ rn = rt_add(map->prefix, map->prefixlen);
- /* remove LSP from kernel */
+ /* LWd.1: remove label from forwarding/switching use */
LIST_FOREACH(rl, &rn->lsp, entry) {
- if (lde_address_find(ln, &rl->nexthop))
- break;
- }
- if (rl) {
- rl->remote_label = NO_LABEL;
- lde_send_delete_klabel(rn, rl);
+ if (lde_address_find(ln, &rl->nexthop)) {
+ lde_send_delete_klabel(rn, rl);
+ rl->remote_label = NO_LABEL;
+ }
}
- /* check recv map list and remove it if available */
+ /* LWd.2: send label release */
+ lde_send_labelrelease(ln, rn, map->label);
+
+ /* LWd.3: check previously received label mapping */
me = (struct lde_map *)fec_find(&ln->recv_map, &rn->fec);
- if (me)
+ if (me && (map->label == NO_LABEL || map->label == me->label))
+ /* LWd.4: remove record of previously received lbl mapping */
lde_map_del(ln, me, 0);
+}
- /* if ordered distribution */
- /* walk over upstream list and send withdraws for LSP that depend on
- * the removed LSP */
+void
+lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
+{
+ struct fec *f;
+ struct rt_node *rn;
+ struct rt_lsp *rl;
+ struct lde_map *me;
+
+ /* LWd.2: send label release */
+ lde_send_labelrelease(ln, NULL, map->label);
- /* if independent distribution and adv on demand */
- /* Generate Event: Recognize New FEC for FEC. */
+ RB_FOREACH(f, fec_tree, &rt) {
+ rn = (struct rt_node *)f;
+
+ /* LWd.1: remove label from forwarding/switching use */
+ LIST_FOREACH(rl, &rn->lsp, entry) {
+ if (lde_address_find(ln, &rl->nexthop)) {
+ lde_send_delete_klabel(rn, rl);
+ rl->remote_label = NO_LABEL;
+ }
+ }
+
+ /* LWd.3: check previously received label mapping */
+ me = (struct lde_map *)fec_find(&ln->recv_map, &rn->fec);
+ if (me && (map->label == NO_LABEL || map->label == me->label))
+ /*
+ * LWd.4: remove record of previously received
+ * label mapping
+ */
+ lde_map_del(ln, me, 0);
+ }
}
diff --git a/usr.sbin/ldpd/ldp.h b/usr.sbin/ldpd/ldp.h
index 3a59fb460e9..e1a4480d8d4 100644
--- a/usr.sbin/ldpd/ldp.h
+++ b/usr.sbin/ldpd/ldp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldp.h,v 1.17 2015/03/21 18:34:01 renato Exp $ */
+/* $OpenBSD: ldp.h,v 1.18 2015/07/19 20:54:17 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -195,7 +195,8 @@ struct address_list_tlv {
#define ADDR_IPV4 0x1
#define ADDR_IPV6 0x2
-#define FEC_ELM_MIN_LEN 4
+#define FEC_ELM_WCARD_LEN 1
+#define FEC_ELM_PREFIX_MIN_LEN 4
#define FEC_WILDCARD 0x01
#define FEC_PREFIX 0x02
#define FEC_IPV4 0x0001
diff --git a/usr.sbin/ldpd/ldpd.h b/usr.sbin/ldpd/ldpd.h
index 31dd4342122..ed600251b57 100644
--- a/usr.sbin/ldpd/ldpd.h
+++ b/usr.sbin/ldpd/ldpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpd.h,v 1.47 2015/07/19 20:50:03 renato Exp $ */
+/* $OpenBSD: ldpd.h,v 1.48 2015/07/19 20:54:17 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -99,6 +99,8 @@ enum imsg_type {
IMSG_MAPPING_ADD_END,
IMSG_RELEASE_ADD,
IMSG_RELEASE_ADD_END,
+ IMSG_WITHDRAW_ADD,
+ IMSG_WITHDRAW_ADD_END,
IMSG_ADDRESS_ADD,
IMSG_ADDRESS_DEL,
IMSG_NOTIFICATION_SEND,
@@ -160,15 +162,14 @@ TAILQ_HEAD(mapping_head, mapping_entry);
struct map {
struct in_addr prefix;
+ u_int8_t prefixlen;
u_int32_t label;
u_int32_t messageid;
u_int32_t requestid;
- u_int8_t prefixlen;
u_int8_t flags;
};
#define F_MAP_WILDCARD 0x01 /* wildcard FEC */
-#define F_MAP_OPTLABEL 0x02 /* optional label present */
-#define F_MAP_REQ_ID 0x04 /* optional request message id present */
+#define F_MAP_REQ_ID 0x02 /* optional request message id present */
struct notify_msg {
u_int32_t messageid;
diff --git a/usr.sbin/ldpd/ldpe.c b/usr.sbin/ldpd/ldpe.c
index 353060b41ec..d7b4172c760 100644
--- a/usr.sbin/ldpd/ldpe.c
+++ b/usr.sbin/ldpd/ldpe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.c,v 1.30 2015/03/21 18:32:01 renato Exp $ */
+/* $OpenBSD: ldpe.c,v 1.31 2015/07/19 20:54:17 renato Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -476,6 +476,7 @@ ldpe_dispatch_lde(int fd, short event, void *bula)
case IMSG_MAPPING_ADD:
case IMSG_RELEASE_ADD:
case IMSG_REQUEST_ADD:
+ case IMSG_WITHDRAW_ADD:
if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
fatalx("invalid size of map request");
memcpy(&map, imsg.data, sizeof(map));
@@ -499,11 +500,15 @@ ldpe_dispatch_lde(int fd, short event, void *bula)
case IMSG_REQUEST_ADD:
nbr_mapping_add(nbr, &nbr->request_list, &map);
break;
+ case IMSG_WITHDRAW_ADD:
+ nbr_mapping_add(nbr, &nbr->withdraw_list, &map);
+ break;
}
break;
case IMSG_MAPPING_ADD_END:
case IMSG_RELEASE_ADD_END:
case IMSG_REQUEST_ADD_END:
+ case IMSG_WITHDRAW_ADD_END:
nbr = nbr_find_peerid(imsg.hdr.peerid);
if (nbr == NULL) {
log_debug("ldpe_dispatch_lde: cannot find "
@@ -526,6 +531,10 @@ ldpe_dispatch_lde(int fd, short event, void *bula)
send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
&nbr->request_list);
break;
+ case IMSG_WITHDRAW_ADD_END:
+ send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW,
+ &nbr->withdraw_list);
+ break;
}
break;
case IMSG_NOTIFICATION_SEND:
diff --git a/usr.sbin/ldpd/log.c b/usr.sbin/ldpd/log.c
index f0a8dd28a74..8a4e1c538b2 100644
--- a/usr.sbin/ldpd/log.c
+++ b/usr.sbin/ldpd/log.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.13 2014/11/03 18:44:36 bluhm Exp $ */
+/* $OpenBSD: log.c,v 1.14 2015/07/19 20:54:17 renato Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -288,6 +288,9 @@ log_fec(struct map *map)
static char buf[32];
char pstr[32];
+ if (map->flags & F_MAP_WILDCARD)
+ return ("wildcard");
+
if (snprintf(buf, sizeof(buf), "%s/%u",
inet_ntop(AF_INET, &map->prefix, pstr, sizeof(pstr)),
map->prefixlen) == -1)