]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_label.c
zebra: Convert socket interface to use `union sockunion`
[mirror_frr.git] / bgpd / bgp_label.c
CommitLineData
cd1964ff
DS
1/* BGP carrying label information
2 * Copyright (C) 2013 Cumulus Networks, Inc.
3 *
4 * This file is part of GNU Zebra.
5 *
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
9 * later version.
10 *
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.
15 *
896014f4
DL
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
cd1964ff
DS
19 */
20
21#include <zebra.h>
22
23#include "command.h"
24#include "thread.h"
25#include "prefix.h"
26#include "zclient.h"
27#include "stream.h"
28#include "network.h"
29#include "log.h"
30#include "memory.h"
31#include "nexthop.h"
32#include "mpls.h"
33
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"
14454c9f 41#include "bgpd/bgp_errors.h"
cd1964ff
DS
42
43extern struct zclient *zclient;
44
d62a17ae 45int bgp_parse_fec_update(void)
cd1964ff 46{
d62a17ae 47 struct stream *s;
48 struct bgp_node *rn;
49 struct bgp *bgp;
50 struct bgp_table *table;
51 struct prefix p;
d7c0a89a 52 uint32_t label;
d62a17ae 53 afi_t afi;
54 safi_t safi;
55
56 s = zclient->ibuf;
57
58 memset(&p, 0, sizeof(struct prefix));
59 p.family = stream_getw(s);
60 p.prefixlen = stream_getc(s);
a85297a7 61 stream_get(p.u.val, s, PSIZE(p.prefixlen));
d62a17ae 62 label = stream_getl(s);
63
64 /* hack for the bgp instance & SAFI = have to send/receive it */
65 afi = family2afi(p.family);
66 safi = SAFI_UNICAST;
67 bgp = bgp_get_default();
68 if (!bgp) {
69 zlog_debug("no default bgp instance");
70 return -1;
71 }
72
73 table = bgp->rib[afi][safi];
74 if (!table) {
75 zlog_debug("no %u unicast table", p.family);
76 return -1;
77 }
78 rn = bgp_node_lookup(table, &p);
79 if (!rn) {
80 zlog_debug("no node for the prefix");
81 return -1;
82 }
83
84 /* treat it as implicit withdraw - the label is invalid */
85 if (label == MPLS_INVALID_LABEL)
86 bgp_unset_valid_label(&rn->local_label);
87 else {
88 label_ntop(label, 1, &rn->local_label);
89 bgp_set_valid_label(&rn->local_label);
90 }
91 SET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
92 bgp_unlock_node(rn);
93 bgp_process(bgp, rn, afi, safi);
94 return 1;
cd1964ff
DS
95}
96
40381db7 97mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_path_info *pi,
d62a17ae 98 struct peer *to, afi_t afi, safi_t safi)
cd1964ff 99{
d62a17ae 100 struct peer *from;
101 mpls_label_t remote_label;
102 int reflect;
cd1964ff 103
40381db7 104 if (!rn || !pi || !to)
d62a17ae 105 return MPLS_INVALID_LABEL;
cd1964ff 106
40381db7
DS
107 remote_label = pi->extra ? pi->extra->label[0] : MPLS_INVALID_LABEL;
108 from = pi->peer;
d62a17ae 109 reflect =
110 ((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
cd1964ff 111
d62a17ae 112 if (reflect
113 && !CHECK_FLAG(to->af_flags[afi][safi],
114 PEER_FLAG_FORCE_NEXTHOP_SELF))
115 return remote_label;
cd1964ff 116
d62a17ae 117 if (CHECK_FLAG(to->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED))
118 return remote_label;
cd1964ff 119
d62a17ae 120 return rn->local_label;
cd1964ff
DS
121}
122
40381db7 123void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_path_info *pi,
4b7e6066 124 int reg)
cd1964ff 125{
d62a17ae 126 struct stream *s;
127 struct prefix *p;
128 int command;
d7c0a89a 129 uint16_t flags = 0;
d62a17ae 130 size_t flags_pos = 0;
131
132 /* Check socket. */
133 if (!zclient || zclient->sock < 0)
134 return;
135
136 p = &(rn->p);
137 s = zclient->obuf;
138 stream_reset(s);
139 command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER;
140 zclient_create_header(s, command, VRF_DEFAULT);
141 flags_pos = stream_get_endp(s); /* save position of 'flags' */
142 stream_putw(s, flags); /* initial flags */
143 stream_putw(s, PREFIX_FAMILY(p));
144 stream_put_prefix(s, p);
145 if (reg) {
40381db7
DS
146 assert(pi);
147 if (pi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
148 if (pi->attr->label_index != BGP_INVALID_LABEL_INDEX) {
d62a17ae 149 flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
40381db7 150 stream_putl(s, pi->attr->label_index);
d62a17ae 151 }
152 }
153 SET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
154 } else
155 UNSET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
156
157 /* Set length and flags */
158 stream_putw_at(s, 0, stream_get_endp(s));
e0b84ba1
DS
159
160 /*
161 * We only need to write new flags if this is a register
162 */
163 if (reg)
164 stream_putw_at(s, flags_pos, flags);
d62a17ae 165
166 zclient_send_message(zclient);
cd1964ff
DS
167}
168
d7c0a89a 169static int bgp_nlri_get_labels(struct peer *peer, uint8_t *pnt, uint8_t plen,
d62a17ae 170 mpls_label_t *label)
cd1964ff 171{
d7c0a89a
QY
172 uint8_t *data = pnt;
173 uint8_t *lim = pnt + plen;
174 uint8_t llen = 0;
175 uint8_t label_depth = 0;
d62a17ae 176
177 for (; data < lim; data += BGP_LABEL_BYTES) {
178 memcpy(label, data, BGP_LABEL_BYTES);
179 llen += BGP_LABEL_BYTES;
180
181 bgp_set_valid_label(label);
182 label_depth += 1;
183
184 if (bgp_is_withdraw_label(label) || label_bos(label))
185 break;
186 }
187
188 /* If we RX multiple labels we will end up keeping only the last
189 * one. We do not yet support a label stack greater than 1. */
190 if (label_depth > 1)
01c4f23c 191 zlog_info("%s rcvd UPDATE with label stack %d deep", peer->host,
d62a17ae 192 label_depth);
193
194 if (!(bgp_is_withdraw_label(label) || label_bos(label)))
01c4f23c 195 flog_warn(
e50f7cfd 196 EC_BGP_INVALID_LABEL_STACK,
d62a17ae 197 "%s rcvd UPDATE with invalid label stack - no bottom of stack",
198 peer->host);
199
200 return llen;
cd1964ff
DS
201}
202
d62a17ae 203int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
204 struct bgp_nlri *packet)
cd1964ff 205{
d7c0a89a
QY
206 uint8_t *pnt;
207 uint8_t *lim;
d62a17ae 208 struct prefix p;
209 int psize = 0;
210 int prefixlen;
211 afi_t afi;
212 safi_t safi;
213 int addpath_encoded;
d7c0a89a 214 uint32_t addpath_id;
d62a17ae 215 mpls_label_t label = MPLS_INVALID_LABEL;
d7c0a89a 216 uint8_t llen;
d62a17ae 217
d62a17ae 218 pnt = packet->nlri;
219 lim = pnt + packet->length;
220 afi = packet->afi;
221 safi = packet->safi;
222 addpath_id = 0;
223
224 addpath_encoded =
225 (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
226 && CHECK_FLAG(peer->af_cap[afi][safi],
227 PEER_CAP_ADDPATH_AF_TX_RCV));
228
229 for (; pnt < lim; pnt += psize) {
230 /* Clear prefix structure. */
231 memset(&p, 0, sizeof(struct prefix));
d62a17ae 232
233 if (addpath_encoded) {
234
235 /* When packet overflow occurs return immediately. */
236 if (pnt + BGP_ADDPATH_ID_LEN > lim)
237 return -1;
238
239 addpath_id = ntohl(*((uint32_t *)pnt));
240 pnt += BGP_ADDPATH_ID_LEN;
241 }
242
243 /* Fetch prefix length. */
244 prefixlen = *pnt++;
245 p.family = afi2family(packet->afi);
246 psize = PSIZE(prefixlen);
247
248 /* sanity check against packet data */
249 if ((pnt + psize) > lim) {
af4c2728 250 flog_err(
e50f7cfd 251 EC_BGP_UPDATE_RCV,
d62a17ae 252 "%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)",
253 peer->host, prefixlen, (uint)(lim - pnt));
254 return -1;
255 }
256
257 /* Fill in the labels */
258 llen = bgp_nlri_get_labels(peer, pnt, psize, &label);
259 p.prefixlen = prefixlen - BSIZE(llen);
260
261 /* There needs to be at least one label */
262 if (prefixlen < 24) {
e50f7cfd 263 flog_err(EC_BGP_UPDATE_RCV,
1c50c1c0
QY
264 "%s [Error] Update packet error"
265 " (wrong label length %d)",
266 peer->host, prefixlen);
d62a17ae 267 bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
268 BGP_NOTIFY_UPDATE_INVAL_NETWORK);
269 return -1;
270 }
271
272 if ((afi == AFI_IP && p.prefixlen > 32)
273 || (afi == AFI_IP6 && p.prefixlen > 128))
274 return -1;
275
276 /* Fetch prefix from NLRI packet */
277 memcpy(&p.u.prefix, pnt + llen, psize - llen);
278
279 /* Check address. */
280 if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) {
281 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
282 /* From RFC4271 Section 6.3:
283 *
284 * If a prefix in the NLRI field is semantically
285 * incorrect
286 * (e.g., an unexpected multicast IP address),
287 * an error SHOULD
288 * be logged locally, and the prefix SHOULD be
289 * ignored.
9d303b37 290 */
af4c2728 291 flog_err(
e50f7cfd 292 EC_BGP_UPDATE_RCV,
d62a17ae 293 "%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring",
294 peer->host, inet_ntoa(p.u.prefix4));
295 continue;
296 }
297 }
298
299 /* Check address. */
300 if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) {
301 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
302 char buf[BUFSIZ];
303
af4c2728 304 flog_err(
e50f7cfd 305 EC_BGP_UPDATE_RCV,
d62a17ae 306 "%s: IPv6 labeled-unicast NLRI is link-local address %s, ignoring",
307 peer->host,
308 inet_ntop(AF_INET6, &p.u.prefix6, buf,
309 BUFSIZ));
310
311 continue;
312 }
313
314 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
315 char buf[BUFSIZ];
316
af4c2728 317 flog_err(
e50f7cfd 318 EC_BGP_UPDATE_RCV,
d62a17ae 319 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
320 peer->host,
321 inet_ntop(AF_INET6, &p.u.prefix6, buf,
322 BUFSIZ));
323
324 continue;
325 }
326 }
327
328 if (attr) {
329 bgp_update(peer, &p, addpath_id, attr, packet->afi,
330 SAFI_UNICAST, ZEBRA_ROUTE_BGP,
b57ba6d2 331 BGP_ROUTE_NORMAL, NULL, &label, 1, 0, NULL);
d62a17ae 332 } else {
333 bgp_withdraw(peer, &p, addpath_id, attr, packet->afi,
334 SAFI_UNICAST, ZEBRA_ROUTE_BGP,
b57ba6d2 335 BGP_ROUTE_NORMAL, NULL, &label, 1, NULL);
d62a17ae 336 }
337 }
338
339 /* Packet length consistency check. */
340 if (pnt != lim) {
af4c2728 341 flog_err(
e50f7cfd 342 EC_BGP_UPDATE_RCV,
d62a17ae 343 "%s [Error] Update packet error / L-U (%zu data remaining after parsing)",
344 peer->host, lim - pnt);
345 return -1;
346 }
347
348 return 0;
cd1964ff 349}