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