1 /* BGP carrying label information
2 * Copyright (C) 2013 Cumulus Networks, Inc.
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "bgpd/bgpd.h"
35 #include "bgpd/bgp_table.h"
36 #include "bgpd/bgp_route.h"
37 #include "bgpd/bgp_attr.h"
38 #include "bgpd/bgp_label.h"
39 #include "bgpd/bgp_packet.h"
40 #include "bgpd/bgp_debug.h"
42 extern struct zclient
*zclient
;
44 int bgp_parse_fec_update(void)
49 struct bgp_table
*table
;
57 memset(&p
, 0, sizeof(struct prefix
));
58 p
.family
= stream_getw(s
);
59 p
.prefixlen
= stream_getc(s
);
60 stream_get(p
.u
.val
, s
, PSIZE(p
.prefixlen
));
61 label
= stream_getl(s
);
63 /* hack for the bgp instance & SAFI = have to send/receive it */
64 afi
= family2afi(p
.family
);
66 bgp
= bgp_get_default();
68 zlog_debug("no default bgp instance");
72 table
= bgp
->rib
[afi
][safi
];
74 zlog_debug("no %u unicast table", p
.family
);
77 rn
= bgp_node_lookup(table
, &p
);
79 zlog_debug("no node for the prefix");
83 /* treat it as implicit withdraw - the label is invalid */
84 if (label
== MPLS_INVALID_LABEL
)
85 bgp_unset_valid_label(&rn
->local_label
);
87 label_ntop(label
, 1, &rn
->local_label
);
88 bgp_set_valid_label(&rn
->local_label
);
90 SET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
92 bgp_process(bgp
, rn
, afi
, safi
);
96 mpls_label_t
bgp_adv_label(struct bgp_node
*rn
, struct bgp_info
*ri
,
97 struct peer
*to
, afi_t afi
, safi_t safi
)
100 mpls_label_t remote_label
;
103 if (!rn
|| !ri
|| !to
)
104 return MPLS_INVALID_LABEL
;
106 remote_label
= ri
->extra
? ri
->extra
->label
[0] : MPLS_INVALID_LABEL
;
109 ((from
->sort
== BGP_PEER_IBGP
) && (to
->sort
== BGP_PEER_IBGP
));
112 && !CHECK_FLAG(to
->af_flags
[afi
][safi
],
113 PEER_FLAG_FORCE_NEXTHOP_SELF
))
116 if (CHECK_FLAG(to
->af_flags
[afi
][safi
], PEER_FLAG_NEXTHOP_UNCHANGED
))
119 return rn
->local_label
;
122 void bgp_reg_dereg_for_label(struct bgp_node
*rn
, struct bgp_info
*ri
, int reg
)
128 size_t flags_pos
= 0;
131 if (!zclient
|| zclient
->sock
< 0)
137 command
= (reg
) ? ZEBRA_FEC_REGISTER
: ZEBRA_FEC_UNREGISTER
;
138 zclient_create_header(s
, command
, VRF_DEFAULT
);
139 flags_pos
= stream_get_endp(s
); /* save position of 'flags' */
140 stream_putw(s
, flags
); /* initial flags */
141 stream_putw(s
, PREFIX_FAMILY(p
));
142 stream_put_prefix(s
, p
);
145 if (ri
->attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
)) {
146 if (ri
->attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
147 flags
|= ZEBRA_FEC_REGISTER_LABEL_INDEX
;
148 stream_putl(s
, ri
->attr
->label_index
);
151 SET_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
);
153 UNSET_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
);
155 /* Set length and flags */
156 stream_putw_at(s
, 0, stream_get_endp(s
));
159 * We only need to write new flags if this is a register
162 stream_putw_at(s
, flags_pos
, flags
);
164 zclient_send_message(zclient
);
167 static int bgp_nlri_get_labels(struct peer
*peer
, uint8_t *pnt
, uint8_t plen
,
171 uint8_t *lim
= pnt
+ plen
;
173 uint8_t label_depth
= 0;
175 for (; data
< lim
; data
+= BGP_LABEL_BYTES
) {
176 memcpy(label
, data
, BGP_LABEL_BYTES
);
177 llen
+= BGP_LABEL_BYTES
;
179 bgp_set_valid_label(label
);
182 if (bgp_is_withdraw_label(label
) || label_bos(label
))
186 /* If we RX multiple labels we will end up keeping only the last
187 * one. We do not yet support a label stack greater than 1. */
189 zlog_warn("%s rcvd UPDATE with label stack %d deep", peer
->host
,
192 if (!(bgp_is_withdraw_label(label
) || label_bos(label
)))
194 "%s rcvd UPDATE with invalid label stack - no bottom of stack",
200 int bgp_nlri_parse_label(struct peer
*peer
, struct attr
*attr
,
201 struct bgp_nlri
*packet
)
212 mpls_label_t label
= MPLS_INVALID_LABEL
;
216 lim
= pnt
+ packet
->length
;
222 (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
223 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
224 PEER_CAP_ADDPATH_AF_TX_RCV
));
226 for (; pnt
< lim
; pnt
+= psize
) {
227 /* Clear prefix structure. */
228 memset(&p
, 0, sizeof(struct prefix
));
230 if (addpath_encoded
) {
232 /* When packet overflow occurs return immediately. */
233 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
236 addpath_id
= ntohl(*((uint32_t *)pnt
));
237 pnt
+= BGP_ADDPATH_ID_LEN
;
240 /* Fetch prefix length. */
242 p
.family
= afi2family(packet
->afi
);
243 psize
= PSIZE(prefixlen
);
245 /* sanity check against packet data */
246 if ((pnt
+ psize
) > lim
) {
248 "%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)",
249 peer
->host
, prefixlen
, (uint
)(lim
- pnt
));
253 /* Fill in the labels */
254 llen
= bgp_nlri_get_labels(peer
, pnt
, psize
, &label
);
255 p
.prefixlen
= prefixlen
- BSIZE(llen
);
257 /* There needs to be at least one label */
258 if (prefixlen
< 24) {
260 "%s [Error] Update packet error"
261 " (wrong label length %d)",
262 peer
->host
, prefixlen
);
263 bgp_notify_send(peer
, BGP_NOTIFY_UPDATE_ERR
,
264 BGP_NOTIFY_UPDATE_INVAL_NETWORK
);
268 if ((afi
== AFI_IP
&& p
.prefixlen
> 32)
269 || (afi
== AFI_IP6
&& p
.prefixlen
> 128))
272 /* Fetch prefix from NLRI packet */
273 memcpy(&p
.u
.prefix
, pnt
+ llen
, psize
- llen
);
276 if (afi
== AFI_IP
&& safi
== SAFI_LABELED_UNICAST
) {
277 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
278 /* From RFC4271 Section 6.3:
280 * If a prefix in the NLRI field is semantically
282 * (e.g., an unexpected multicast IP address),
284 * be logged locally, and the prefix SHOULD be
288 "%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring",
289 peer
->host
, inet_ntoa(p
.u
.prefix4
));
295 if (afi
== AFI_IP6
&& safi
== SAFI_LABELED_UNICAST
) {
296 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
300 "%s: IPv6 labeled-unicast NLRI is link-local address %s, ignoring",
302 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
308 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
312 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
314 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
322 bgp_update(peer
, &p
, addpath_id
, attr
, packet
->afi
,
323 SAFI_UNICAST
, ZEBRA_ROUTE_BGP
,
324 BGP_ROUTE_NORMAL
, NULL
, &label
, 1, 0, NULL
);
326 bgp_withdraw(peer
, &p
, addpath_id
, attr
, packet
->afi
,
327 SAFI_UNICAST
, ZEBRA_ROUTE_BGP
,
328 BGP_ROUTE_NORMAL
, NULL
, &label
, 1, NULL
);
332 /* Packet length consistency check. */
335 "%s [Error] Update packet error / L-U (%zu data remaining after parsing)",
336 peer
->host
, lim
- pnt
);