summaryrefslogtreecommitdiff
path: root/usr.sbin/ldpd/labelmapping.c
diff options
context:
space:
mode:
authorRenato Westphal <renato@cvs.openbsd.org>2013-10-17 17:52:22 +0000
committerRenato Westphal <renato@cvs.openbsd.org>2013-10-17 17:52:22 +0000
commitb2700df3a83efc7e90ff167b58338c5c3078608c (patch)
tree34cd207737da7daf4098a7545400d4895a3e2198 /usr.sbin/ldpd/labelmapping.c
parente8cdcdc1d914a178d912f18cec466ed895e5e4fb (diff)
Respect the max pdu length and merge all send_label* functions into
a single generic function.
Diffstat (limited to 'usr.sbin/ldpd/labelmapping.c')
-rw-r--r--usr.sbin/ldpd/labelmapping.c198
1 files changed, 42 insertions, 156 deletions
diff --git a/usr.sbin/ldpd/labelmapping.c b/usr.sbin/ldpd/labelmapping.c
index 8a4fc65344b..82765ed0305 100644
--- a/usr.sbin/ldpd/labelmapping.c
+++ b/usr.sbin/ldpd/labelmapping.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: labelmapping.c,v 1.27 2013/10/17 17:47:03 renato Exp $ */
+/* $OpenBSD: labelmapping.c,v 1.28 2013/10/17 17:52:20 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -48,186 +48,71 @@ int tlv_decode_label(struct nbr *, struct ldp_msg *, char *, u_int16_t,
int tlv_decode_fec_elm(struct nbr *, struct ldp_msg *, char *, u_int16_t,
u_int8_t *, u_int32_t *, u_int8_t *);
-/* Label Mapping Message */
-void
-send_labelmapping(struct nbr *nbr)
+static void
+enqueue_pdu(struct nbr *nbr, struct ibuf *buf, u_int16_t size)
{
- struct ibuf *buf;
- struct mapping_entry *me;
struct ldp_hdr *ldp_hdr;
- u_int16_t tlv_size, size;
-
- if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL)
- fatal("send_labelmapping");
-
- /* real size will be set up later */
- gen_ldp_hdr(buf, 0);
-
- size = LDP_HDR_SIZE - TLV_HDR_LEN;
-
- TAILQ_FOREACH(me, &nbr->mapping_list, entry) {
- tlv_size = BASIC_LABEL_MAP_LEN + PREFIX_SIZE(me->map.prefixlen);
- if (me->map.flags & F_MAP_REQ_ID)
- tlv_size += REQID_TLV_LEN;
- size += tlv_size;
-
- gen_msg_tlv(buf, MSG_TYPE_LABELMAPPING, tlv_size);
- gen_fec_tlv(buf, me->map.prefix, me->map.prefixlen);
- gen_label_tlv(buf, me->map.label);
- if (me->map.flags & F_MAP_REQ_ID)
- gen_reqid_tlv(buf, me->map.requestid);
- }
-
- /* XXX: should we remove them first? */
- mapping_list_clr(&nbr->mapping_list);
ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr));
ldp_hdr->length = htons(size);
-
evbuf_enqueue(&nbr->tcp->wbuf, buf);
- nbr_fsm(nbr, NBR_EVT_PDU_SENT);
}
-/* Label Request Message */
+/* Generic function that handles all Label Message types */
void
-send_labelrequest(struct nbr *nbr)
+send_labelmessage(struct nbr *nbr, u_int16_t type, struct mapping_head *mh)
{
- struct ibuf *buf;
+ struct ibuf *buf = NULL;
struct mapping_entry *me;
- struct ldp_hdr *ldp_hdr;
- u_int16_t tlv_size, size;
-
- if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL)
- fatal("send_labelrequest");
-
- /* real size will be set up later */
- gen_ldp_hdr(buf, 0);
-
- size = LDP_HDR_SIZE - TLV_HDR_LEN;
-
- TAILQ_FOREACH(me, &nbr->request_list, entry) {
- tlv_size = PREFIX_SIZE(me->map.prefixlen);
- size += tlv_size;
-
- gen_msg_tlv(buf, MSG_TYPE_LABELREQUEST, tlv_size);
- gen_fec_tlv(buf, me->map.prefix, me->map.prefixlen);
- }
-
- /* XXX: should we remove them first? */
- mapping_list_clr(&nbr->request_list);
+ u_int16_t tlv_size, size = 0;
+ int first = 1;
- ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr));
- ldp_hdr->length = htons(size);
+ while ((me = TAILQ_FIRST(mh)) != NULL) {
+ /* generate pdu */
+ if (first) {
+ if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL)
+ fatal("send_labelmapping");
- evbuf_enqueue(&nbr->tcp->wbuf, buf);
- nbr_fsm(nbr, NBR_EVT_PDU_SENT);
-}
+ /* real size will be set up later */
+ gen_ldp_hdr(buf, 0);
-/* Label Withdraw Message */
-void
-send_labelwithdraw(struct nbr *nbr)
-{
- struct ibuf *buf;
- struct mapping_entry *me;
- struct ldp_hdr *ldp_hdr;
- u_int16_t tlv_size, size;
-
- if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL)
- fatal("send_labelwithdraw");
-
- /* real size will be set up later */
- gen_ldp_hdr(buf, 0);
+ size = LDP_HDR_PDU_LEN;
+ first = 0;
+ }
- size = LDP_HDR_SIZE - TLV_HDR_LEN;
+ /* 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 += LABEL_TLV_LEN;
+ if (me->map.flags & F_MAP_REQ_ID)
+ tlv_size += REQID_TLV_LEN;
- TAILQ_FOREACH(me, &nbr->withdraw_list, entry) {
- if (me->map.label == NO_LABEL)
- tlv_size = PREFIX_SIZE(me->map.prefixlen);
- else
- tlv_size = BASIC_LABEL_MAP_LEN +
- PREFIX_SIZE(me->map.prefixlen);
+ /* maximum pdu length exceeded, we need a new ldp pdu */
+ if (size + tlv_size > LDP_MAX_LEN) {
+ enqueue_pdu(nbr, buf, size);
+ first = 1;
+ continue;
+ }
size += tlv_size;
- gen_msg_tlv(buf, MSG_TYPE_LABELWITHDRAW, tlv_size);
+ /* append message and tlvs */
+ gen_msg_tlv(buf, type, tlv_size);
gen_fec_tlv(buf, me->map.prefix, me->map.prefixlen);
-
- if (me->map.label != NO_LABEL)
+ if (type == MSG_TYPE_LABELMAPPING ||
+ me->map.flags & F_MAP_OPTLABEL)
gen_label_tlv(buf, me->map.label);
- }
-
- /* XXX: should we remove them first? */
- mapping_list_clr(&nbr->withdraw_list);
-
- ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr));
- ldp_hdr->length = htons(size);
-
- evbuf_enqueue(&nbr->tcp->wbuf, buf);
- nbr_fsm(nbr, NBR_EVT_PDU_SENT);
-}
-
-/* Label Release Message */
-void
-send_labelrelease(struct nbr *nbr)
-{
- struct ibuf *buf;
- struct mapping_entry *me;
- struct ldp_hdr *ldp_hdr;
- u_int16_t tlv_size, size;
-
- if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL)
- fatal("send_labelrelease");
-
- /* real size will be set up later */
- gen_ldp_hdr(buf, 0);
-
- size = LDP_HDR_SIZE - TLV_HDR_LEN;
-
- TAILQ_FOREACH(me, &nbr->release_list, entry) {
- if (me->map.label == NO_LABEL)
- tlv_size = PREFIX_SIZE(me->map.prefixlen);
- else
- tlv_size = BASIC_LABEL_MAP_LEN +
- PREFIX_SIZE(me->map.prefixlen);
-
- size += tlv_size;
-
- gen_msg_tlv(buf, MSG_TYPE_LABELRELEASE, tlv_size);
- gen_fec_tlv(buf, me->map.prefix, me->map.prefixlen);
+ if (me->map.flags & F_MAP_REQ_ID)
+ gen_reqid_tlv(buf, me->map.requestid);
- if (me->map.label != NO_LABEL)
- gen_label_tlv(buf, me->map.label);
+ TAILQ_REMOVE(mh, me, entry);
+ free(me);
}
- /* XXX: should we remove them first? */
- mapping_list_clr(&nbr->release_list);
-
- ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr));
- ldp_hdr->length = htons(size);
-
- evbuf_enqueue(&nbr->tcp->wbuf, buf);
- nbr_fsm(nbr, NBR_EVT_PDU_SENT);
-}
-
-/* Label Abort Req Message */
-void
-send_labelabortreq(struct nbr *nbr)
-{
- struct ibuf *buf;
- u_int16_t size;
-
- if ((buf = ibuf_open(LDP_MAX_LEN)) == NULL)
- fatal("send_labelabortreq");
-
- size = LDP_HDR_SIZE + sizeof(struct ldp_msg);
+ enqueue_pdu(nbr, buf, size);
- gen_ldp_hdr(buf, size);
-
- size -= LDP_HDR_SIZE;
-
- gen_msg_tlv(buf, MSG_TYPE_LABELABORTREQ, size);
-
- evbuf_enqueue(&nbr->tcp->wbuf, buf);
nbr_fsm(nbr, NBR_EVT_PDU_SENT);
}
@@ -239,6 +124,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, u_int16_t len, u_int16_t type)
struct tlv ft;
u_int32_t label, reqid;
u_int8_t flags = 0;
+
int feclen, lbllen, tlen;
u_int8_t addr_type;
struct mapping_entry *me;