Line data Source code
1 : /* BGP Extended Communities Attribute.
2 : * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
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 : *
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
19 : */
20 :
21 : #ifndef _QUAGGA_BGP_ECOMMUNITY_H
22 : #define _QUAGGA_BGP_ECOMMUNITY_H
23 :
24 : #include "bgpd/bgp_route.h"
25 : #include "bgpd/bgp_rpki.h"
26 : #include "bgpd/bgpd.h"
27 :
28 : /* Refer to rfc7153 for the IANA registry definitions. These are
29 : * updated by other standards like rfc7674.
30 : */
31 : /* High-order octet of the Extended Communities type field. */
32 : #define ECOMMUNITY_ENCODE_AS 0x00
33 : #define ECOMMUNITY_ENCODE_IP 0x01
34 : #define ECOMMUNITY_ENCODE_AS4 0x02
35 : #define ECOMMUNITY_ENCODE_OPAQUE 0x03
36 : #define ECOMMUNITY_ENCODE_EVPN 0x06
37 : #define ECOMMUNITY_ENCODE_REDIRECT_IP_NH 0x08 /* Flow Spec */
38 : /* Generic Transitive Experimental */
39 : #define ECOMMUNITY_ENCODE_TRANS_EXP 0x80
40 :
41 : /* RFC7674 */
42 : #define ECOMMUNITY_EXTENDED_COMMUNITY_PART_2 0x81
43 : #define ECOMMUNITY_EXTENDED_COMMUNITY_PART_3 0x82
44 :
45 : /* Non-transitive extended community types. */
46 : #define ECOMMUNITY_ENCODE_AS_NON_TRANS 0x40
47 : #define ECOMMUNITY_ENCODE_IP_NON_TRANS 0x41
48 : #define ECOMMUNITY_ENCODE_AS4_NON_TRANS 0x42
49 : #define ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS 0x43
50 :
51 : /* Low-order octet of the Extended Communities type field. */
52 : /* Note: This really depends on the high-order octet. This means that
53 : * multiple definitions for the same value are possible.
54 : */
55 : #define ECOMMUNITY_ORIGIN_VALIDATION_STATE 0x00
56 : #define ECOMMUNITY_ROUTE_TARGET 0x02
57 : #define ECOMMUNITY_SITE_ORIGIN 0x03
58 : #define ECOMMUNITY_LINK_BANDWIDTH 0x04
59 : #define ECOMMUNITY_TRAFFIC_RATE 0x06 /* Flow Spec */
60 : #define ECOMMUNITY_TRAFFIC_ACTION 0x07
61 : #define ECOMMUNITY_REDIRECT_VRF 0x08
62 : #define ECOMMUNITY_TRAFFIC_MARKING 0x09
63 : #define ECOMMUNITY_REDIRECT_IP_NH 0x00
64 : /* from IANA: bgp-extended-communities/bgp-extended-communities.xhtml
65 : * 0x0c Flow-spec Redirect to IPv4 - draft-ietf-idr-flowspec-redirect
66 : */
67 : #define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4 0x0c
68 : /* from draft-ietf-idr-flow-spec-v6-09
69 : * 0x0b Flow-spec Redirect to IPv6
70 : */
71 : #define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0b
72 :
73 : /* Low-order octet of the Extended Communities type field for EVPN types */
74 : #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
75 : #define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01
76 : #define ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT 0x02
77 : #define ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC 0x03
78 : #define ECOMMUNITY_EVPN_SUBTYPE_DF_ELECTION 0x06
79 : #define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d
80 : #define ECOMMUNITY_EVPN_SUBTYPE_ND 0x08
81 :
82 : #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01
83 :
84 : /* DF alg bits - only lower 5 bits are applicable */
85 : #define ECOMMUNITY_EVPN_SUBTYPE_DF_ALG_BITS 0x1f
86 :
87 : #define ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG 0x01
88 : #define ECOMMUNITY_EVPN_SUBTYPE_ND_OVERRIDE_FLAG 0x02
89 : #define ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG 0x04
90 :
91 : #define ECOMMUNITY_EVPN_SUBTYPE_ESI_SA_FLAG (1 << 0) /* single-active */
92 :
93 : /* Low-order octet of the Extended Communities type field for OPAQUE types */
94 : #define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c
95 :
96 : /* Extended communities attribute string format. */
97 : #define ECOMMUNITY_FORMAT_ROUTE_MAP 0
98 : #define ECOMMUNITY_FORMAT_COMMUNITY_LIST 1
99 : #define ECOMMUNITY_FORMAT_DISPLAY 2
100 :
101 : /* Extended Communities value is eight octet long. */
102 : #define ECOMMUNITY_SIZE 8
103 : #define IPV6_ECOMMUNITY_SIZE 20
104 :
105 : /* Extended Community Origin Validation State */
106 : enum ecommunity_origin_validation_states {
107 : ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID,
108 : ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND,
109 : ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID,
110 : ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED
111 : };
112 :
113 : /* Extended Communities type flag. */
114 : #define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40
115 :
116 : /* Extended Community readable string length */
117 : #define ECOMMUNITY_STRLEN 64
118 :
119 : /* Extended Communities attribute. */
120 : struct ecommunity {
121 : /* Reference counter. */
122 : unsigned long refcnt;
123 :
124 : /* Size of Each Unit of Extended Communities attribute.
125 : * to differentiate between IPv6 ext comm and ext comm
126 : */
127 : uint8_t unit_size;
128 :
129 : /* Size of Extended Communities attribute. */
130 : uint32_t size;
131 :
132 : /* Extended Communities value. */
133 : uint8_t *val;
134 :
135 : /* Human readable format string. */
136 : char *str;
137 :
138 : /* Disable IEEE floating-point encoding for extended community */
139 : bool disable_ieee_floating;
140 : };
141 :
142 : struct ecommunity_as {
143 : as_t as;
144 : uint32_t val;
145 : };
146 :
147 : struct ecommunity_ip {
148 : struct in_addr ip;
149 : uint16_t val;
150 : };
151 :
152 : struct ecommunity_ip6 {
153 : struct in6_addr ip;
154 : uint16_t val;
155 : };
156 :
157 : /* Extended community value is eight octet. */
158 : struct ecommunity_val {
159 : char val[ECOMMUNITY_SIZE];
160 : };
161 :
162 : /* IPv6 Extended community value is eight octet. */
163 : struct ecommunity_val_ipv6 {
164 : char val[IPV6_ECOMMUNITY_SIZE];
165 : };
166 :
167 : #define ecom_length_size(X, Y) ((X)->size * (Y))
168 :
169 : /*
170 : * Encode BGP Route Target AS:nn.
171 : */
172 0 : static inline void encode_route_target_as(as_t as, uint32_t val,
173 : struct ecommunity_val *eval)
174 : {
175 0 : eval->val[0] = ECOMMUNITY_ENCODE_AS;
176 0 : eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
177 0 : eval->val[2] = (as >> 8) & 0xff;
178 0 : eval->val[3] = as & 0xff;
179 0 : eval->val[4] = (val >> 24) & 0xff;
180 0 : eval->val[5] = (val >> 16) & 0xff;
181 0 : eval->val[6] = (val >> 8) & 0xff;
182 0 : eval->val[7] = val & 0xff;
183 : }
184 :
185 : /*
186 : * Encode BGP Route Target IP:nn.
187 : */
188 : static inline void encode_route_target_ip(struct in_addr ip, uint16_t val,
189 : struct ecommunity_val *eval)
190 : {
191 : eval->val[0] = ECOMMUNITY_ENCODE_IP;
192 : eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
193 : memcpy(&eval->val[2], &ip, sizeof(struct in_addr));
194 : eval->val[6] = (val >> 8) & 0xff;
195 : eval->val[7] = val & 0xff;
196 : }
197 :
198 : /*
199 : * Encode BGP Route Target AS4:nn.
200 : */
201 : static inline void encode_route_target_as4(as_t as, uint16_t val,
202 : struct ecommunity_val *eval)
203 : {
204 : eval->val[0] = ECOMMUNITY_ENCODE_AS4;
205 : eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
206 : eval->val[2] = (as >> 24) & 0xff;
207 : eval->val[3] = (as >> 16) & 0xff;
208 : eval->val[4] = (as >> 8) & 0xff;
209 : eval->val[5] = as & 0xff;
210 : eval->val[6] = (val >> 8) & 0xff;
211 : eval->val[7] = val & 0xff;
212 : }
213 :
214 : /* Helper function to convert uint32 to IEEE-754 Floating Point */
215 4 : static uint32_t uint32_to_ieee_float_uint32(uint32_t u)
216 : {
217 4 : union {
218 : float r;
219 : uint32_t d;
220 4 : } f = {.r = (float)u};
221 :
222 4 : return f.d;
223 : }
224 :
225 : /*
226 : * Encode BGP Link Bandwidth extended community
227 : * bandwidth (bw) is in bytes-per-sec
228 : */
229 4 : static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
230 : struct ecommunity_val *eval,
231 : bool disable_ieee_floating)
232 : {
233 8 : uint32_t bandwidth =
234 4 : disable_ieee_floating ? bw : uint32_to_ieee_float_uint32(bw);
235 :
236 4 : memset(eval, 0, sizeof(*eval));
237 4 : eval->val[0] = ECOMMUNITY_ENCODE_AS;
238 4 : if (non_trans)
239 0 : eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE;
240 4 : eval->val[1] = ECOMMUNITY_LINK_BANDWIDTH;
241 4 : eval->val[2] = (as >> 8) & 0xff;
242 4 : eval->val[3] = as & 0xff;
243 4 : eval->val[4] = (bandwidth >> 24) & 0xff;
244 4 : eval->val[5] = (bandwidth >> 16) & 0xff;
245 4 : eval->val[6] = (bandwidth >> 8) & 0xff;
246 4 : eval->val[7] = bandwidth & 0xff;
247 4 : }
248 :
249 0 : static inline void encode_origin_validation_state(enum rpki_states state,
250 : struct ecommunity_val *eval)
251 : {
252 0 : enum ecommunity_origin_validation_states ovs_state =
253 : ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED;
254 :
255 0 : switch (state) {
256 : case RPKI_VALID:
257 : ovs_state = ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID;
258 : break;
259 : case RPKI_NOTFOUND:
260 : ovs_state = ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND;
261 : break;
262 : case RPKI_INVALID:
263 : ovs_state = ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID;
264 : break;
265 : case RPKI_NOT_BEING_USED:
266 : break;
267 : }
268 :
269 0 : memset(eval, 0, sizeof(*eval));
270 0 : eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS;
271 0 : eval->val[1] = ECOMMUNITY_ORIGIN_VALIDATION_STATE;
272 0 : eval->val[7] = ovs_state;
273 0 : }
274 :
275 : extern void ecommunity_init(void);
276 : extern void ecommunity_finish(void);
277 : extern void ecommunity_free(struct ecommunity **);
278 : extern struct ecommunity *ecommunity_parse(uint8_t *, unsigned short,
279 : bool disable_ieee_floating);
280 : extern struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt,
281 : unsigned short length,
282 : bool disable_ieee_floating);
283 : extern struct ecommunity *ecommunity_dup(struct ecommunity *);
284 : extern struct ecommunity *ecommunity_merge(struct ecommunity *,
285 : struct ecommunity *);
286 : extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *);
287 : extern struct ecommunity *ecommunity_intern(struct ecommunity *);
288 : extern bool ecommunity_cmp(const void *arg1, const void *arg2);
289 : extern void ecommunity_unintern(struct ecommunity **ecommunity);
290 : extern unsigned int ecommunity_hash_make(const void *);
291 : extern struct ecommunity *ecommunity_str2com(const char *, int, int);
292 : extern struct ecommunity *ecommunity_str2com_ipv6(const char *str, int type,
293 : int keyword_included);
294 : extern char *ecommunity_ecom2str(struct ecommunity *, int, int);
295 : extern void ecommunity_strfree(char **s);
296 : extern bool ecommunity_include(struct ecommunity *e1, struct ecommunity *e2);
297 : extern bool ecommunity_match(const struct ecommunity *,
298 : const struct ecommunity *);
299 : extern char *ecommunity_str(struct ecommunity *);
300 : extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *,
301 : uint8_t, uint8_t);
302 :
303 : extern bool ecommunity_add_val(struct ecommunity *ecom,
304 : struct ecommunity_val *eval,
305 : bool unique, bool overwrite);
306 : extern bool ecommunity_add_val_ipv6(struct ecommunity *ecom,
307 : struct ecommunity_val_ipv6 *eval,
308 : bool unique, bool overwrite);
309 :
310 : /* for vpn */
311 : extern struct ecommunity *ecommunity_new(void);
312 : extern bool ecommunity_strip(struct ecommunity *ecom, uint8_t type,
313 : uint8_t subtype);
314 : extern struct ecommunity *ecommunity_new(void);
315 : extern bool ecommunity_del_val(struct ecommunity *ecom,
316 : struct ecommunity_val *eval);
317 : struct bgp_pbr_entry_action;
318 : extern int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
319 : struct bgp_pbr_entry_action *api,
320 : afi_t afi);
321 :
322 : extern void bgp_compute_aggregate_ecommunity(
323 : struct bgp_aggregate *aggregate,
324 : struct ecommunity *ecommunity);
325 :
326 : extern void bgp_compute_aggregate_ecommunity_hash(
327 : struct bgp_aggregate *aggregate,
328 : struct ecommunity *ecommunity);
329 : extern void bgp_compute_aggregate_ecommunity_val(
330 : struct bgp_aggregate *aggregate);
331 : extern void bgp_remove_ecommunity_from_aggregate(
332 : struct bgp_aggregate *aggregate,
333 : struct ecommunity *ecommunity);
334 : extern void bgp_remove_ecomm_from_aggregate_hash(
335 : struct bgp_aggregate *aggregate,
336 : struct ecommunity *ecommunity);
337 : extern void bgp_aggr_ecommunity_remove(void *arg);
338 : extern const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom,
339 : uint32_t *bw);
340 : extern struct ecommunity *ecommunity_replace_linkbw(as_t as,
341 : struct ecommunity *ecom,
342 : uint64_t cum_bw,
343 : bool disable_ieee_floating);
344 :
345 0 : static inline void ecommunity_strip_rts(struct ecommunity *ecom)
346 : {
347 0 : uint8_t subtype = ECOMMUNITY_ROUTE_TARGET;
348 :
349 0 : ecommunity_strip(ecom, ECOMMUNITY_ENCODE_AS, subtype);
350 0 : ecommunity_strip(ecom, ECOMMUNITY_ENCODE_IP, subtype);
351 0 : ecommunity_strip(ecom, ECOMMUNITY_ENCODE_AS4, subtype);
352 0 : }
353 : extern struct ecommunity *
354 : ecommunity_add_origin_validation_state(enum rpki_states rpki_state,
355 : struct ecommunity *ecom);
356 : #endif /* _QUAGGA_BGP_ECOMMUNITY_H */
|