]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_ecommunity.h
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / bgpd / bgp_ecommunity.h
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/* BGP Extended Communities Attribute.
896014f4 3 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
896014f4 4 */
718e3744 5
00d252cb 6#ifndef _QUAGGA_BGP_ECOMMUNITY_H
7#define _QUAGGA_BGP_ECOMMUNITY_H
8
5b820d9e 9#include "bgpd/bgp_route.h"
7b27cf7b 10#include "bgpd/bgp_rpki.h"
f4bd90c5 11#include "bgpd/bgpd.h"
5b820d9e 12
7e3ebfd1 13/* Refer to rfc7153 for the IANA registry definitions. These are
14 * updated by other standards like rfc7674.
15 */
718e3744 16/* High-order octet of the Extended Communities type field. */
17#define ECOMMUNITY_ENCODE_AS 0x00
18#define ECOMMUNITY_ENCODE_IP 0x01
0b2aa3a0 19#define ECOMMUNITY_ENCODE_AS4 0x02
0014c301 20#define ECOMMUNITY_ENCODE_OPAQUE 0x03
e82202b7 21#define ECOMMUNITY_ENCODE_EVPN 0x06
b72220fc 22#define ECOMMUNITY_ENCODE_REDIRECT_IP_NH 0x08 /* Flow Spec */
7e3ebfd1 23/* Generic Transitive Experimental */
24#define ECOMMUNITY_ENCODE_TRANS_EXP 0x80
25
a8d72b61
PG
26/* RFC7674 */
27#define ECOMMUNITY_EXTENDED_COMMUNITY_PART_2 0x81
28#define ECOMMUNITY_EXTENDED_COMMUNITY_PART_3 0x82
718e3744 29
7e3ebfd1 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
0014c301 36/* Low-order octet of the Extended Communities type field. */
7e3ebfd1 37/* Note: This really depends on the high-order octet. This means that
38 * multiple definitions for the same value are possible.
39 */
7b27cf7b 40#define ECOMMUNITY_ORIGIN_VALIDATION_STATE 0x00
718e3744 41#define ECOMMUNITY_ROUTE_TARGET 0x02
42#define ECOMMUNITY_SITE_ORIGIN 0x03
650b0511 43#define ECOMMUNITY_LINK_BANDWIDTH 0x04
a8d72b61
PG
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
2551b26e
PG
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
9a659715
PG
53/* from draft-ietf-idr-flow-spec-v6-09
54 * 0x0b Flow-spec Redirect to IPv6
55 */
56#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0b
718e3744 57
128ea8ab 58/* Low-order octet of the Extended Communities type field for EVPN types */
1e27ef50
PG
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
74e2bd89 63#define ECOMMUNITY_EVPN_SUBTYPE_DF_ELECTION 0x06
1e27ef50 64#define ECOMMUNITY_EVPN_SUBTYPE_DEF_GW 0x0d
68e33151 65#define ECOMMUNITY_EVPN_SUBTYPE_ND 0x08
1e27ef50 66
128ea8ab 67#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01
7904e9fd 68
74e2bd89
AK
69/* DF alg bits - only lower 5 bits are applicable */
70#define ECOMMUNITY_EVPN_SUBTYPE_DF_ALG_BITS 0x1f
71
7904e9fd
AK
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
128ea8ab 75
4248407b
AK
76#define ECOMMUNITY_EVPN_SUBTYPE_ESI_SA_FLAG (1 << 0) /* single-active */
77
0014c301
LB
78/* Low-order octet of the Extended Communities type field for OPAQUE types */
79#define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c
80
718e3744 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
c6423c31 88#define IPV6_ECOMMUNITY_SIZE 20
718e3744 89
7b27cf7b
DA
90/* Extended Community Origin Validation State */
91enum ecommunity_origin_validation_states {
7b27cf7b
DA
92 ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID,
93 ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND,
324e8b1f
DA
94 ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID,
95 ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED
7b27cf7b
DA
96};
97
4372df71 98/* Extended Communities type flag. */
7c40bf39 99#define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40
4372df71 100
f5e04c75
PR
101/* Extended Community readable string length */
102#define ECOMMUNITY_STRLEN 64
103
c9a25614
DA
104/* Node Target Extended Communities */
105#define ECOMMUNITY_NODE_TARGET 0x09
106#define ECOMMUNITY_NODE_TARGET_RESERVED 0
107
718e3744 108/* Extended Communities attribute. */
d62a17ae 109struct ecommunity {
110 /* Reference counter. */
111 unsigned long refcnt;
718e3744 112
9a659715
PG
113 /* Size of Each Unit of Extended Communities attribute.
114 * to differentiate between IPv6 ext comm and ext comm
115 */
c6423c31 116 uint8_t unit_size;
9a659715 117
d62a17ae 118 /* Size of Extended Communities attribute. */
f6e07e1b 119 uint32_t size;
718e3744 120
d62a17ae 121 /* Extended Communities value. */
d7c0a89a 122 uint8_t *val;
718e3744 123
d62a17ae 124 /* Human readable format string. */
125 char *str;
27aa23a4
DA
126
127 /* Disable IEEE floating-point encoding for extended community */
128 bool disable_ieee_floating;
718e3744 129};
130
5a0ccebf
QY
131struct ecommunity_as {
132 as_t as;
133 uint32_t val;
134};
135
136struct ecommunity_ip {
137 struct in_addr ip;
138 uint16_t val;
139};
140
9a659715
PG
141struct ecommunity_ip6 {
142 struct in6_addr ip;
143 uint16_t val;
144};
145
718e3744 146/* Extended community value is eight octet. */
d62a17ae 147struct ecommunity_val {
148 char val[ECOMMUNITY_SIZE];
718e3744 149};
150
9a659715
PG
151/* IPv6 Extended community value is eight octet. */
152struct ecommunity_val_ipv6 {
153 char val[IPV6_ECOMMUNITY_SIZE];
154};
155
156#define ecom_length_size(X, Y) ((X)->size * (Y))
157
c5900768 158/*
159 * Encode BGP Route Target AS:nn.
160 */
d7c0a89a 161static inline void encode_route_target_as(as_t as, uint32_t val,
8f2a51b7
DA
162 struct ecommunity_val *eval,
163 bool trans)
c5900768 164{
d62a17ae 165 eval->val[0] = ECOMMUNITY_ENCODE_AS;
8f2a51b7
DA
166 if (!trans)
167 eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE;
d62a17ae 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;
c5900768 175}
176
177/*
178 * Encode BGP Route Target IP:nn.
179 */
8f2a51b7
DA
180static inline void encode_route_target_ip(struct in_addr *ip, uint16_t val,
181 struct ecommunity_val *eval,
182 bool trans)
c5900768 183{
d62a17ae 184 eval->val[0] = ECOMMUNITY_ENCODE_IP;
8f2a51b7
DA
185 if (!trans)
186 eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE;
d62a17ae 187 eval->val[1] = ECOMMUNITY_ROUTE_TARGET;
8f2a51b7 188 memcpy(&eval->val[2], ip, sizeof(struct in_addr));
d62a17ae 189 eval->val[6] = (val >> 8) & 0xff;
190 eval->val[7] = val & 0xff;
c5900768 191}
192
193/*
194 * Encode BGP Route Target AS4:nn.
195 */
d7c0a89a 196static inline void encode_route_target_as4(as_t as, uint16_t val,
8f2a51b7
DA
197 struct ecommunity_val *eval,
198 bool trans)
c5900768 199{
d62a17ae 200 eval->val[0] = ECOMMUNITY_ENCODE_AS4;
8f2a51b7
DA
201 if (!trans)
202 eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE;
d62a17ae 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;
c5900768 210}
211
8bcaad3d
DA
212/* Helper function to convert uint32 to IEEE-754 Floating Point */
213static 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
ca9ac3ef 223/*
224 * Encode BGP Link Bandwidth extended community
225 * bandwidth (bw) is in bytes-per-sec
226 */
227static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
27aa23a4
DA
228 struct ecommunity_val *eval,
229 bool disable_ieee_floating)
ca9ac3ef 230{
27aa23a4
DA
231 uint32_t bandwidth =
232 disable_ieee_floating ? bw : uint32_to_ieee_float_uint32(bw);
8bcaad3d 233
ca9ac3ef 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;
8bcaad3d
DA
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;
ca9ac3ef 245}
246
7b27cf7b
DA
247static 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
c9a25614
DA
273static 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
d62a17ae 293extern void ecommunity_init(void);
294extern void ecommunity_finish(void);
295extern void ecommunity_free(struct ecommunity **);
27aa23a4
DA
296extern struct ecommunity *ecommunity_parse(uint8_t *, unsigned short,
297 bool disable_ieee_floating);
9a659715 298extern struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt,
27aa23a4
DA
299 unsigned short length,
300 bool disable_ieee_floating);
d62a17ae 301extern struct ecommunity *ecommunity_dup(struct ecommunity *);
302extern struct ecommunity *ecommunity_merge(struct ecommunity *,
303 struct ecommunity *);
304extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *);
305extern struct ecommunity *ecommunity_intern(struct ecommunity *);
74df8d6d 306extern bool ecommunity_cmp(const void *arg1, const void *arg2);
df7d4670 307extern void ecommunity_unintern(struct ecommunity **ecommunity);
d8b87afe 308extern unsigned int ecommunity_hash_make(const void *);
d62a17ae 309extern struct ecommunity *ecommunity_str2com(const char *, int, int);
9a659715
PG
310extern struct ecommunity *ecommunity_str2com_ipv6(const char *str, int type,
311 int keyword_included);
d62a17ae 312extern char *ecommunity_ecom2str(struct ecommunity *, int, int);
c7ee6c35 313extern void ecommunity_strfree(char **s);
2d7cdc5b 314extern bool ecommunity_include(struct ecommunity *e1, struct ecommunity *e2);
3dc339cd
DA
315extern bool ecommunity_match(const struct ecommunity *,
316 const struct ecommunity *);
d62a17ae 317extern char *ecommunity_str(struct ecommunity *);
318extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *,
319 uint8_t, uint8_t);
9a659715 320
3dc339cd 321extern bool ecommunity_add_val(struct ecommunity *ecom,
1207a5bc 322 struct ecommunity_val *eval,
323 bool unique, bool overwrite);
9a659715
PG
324extern bool ecommunity_add_val_ipv6(struct ecommunity *ecom,
325 struct ecommunity_val_ipv6 *eval,
326 bool unique, bool overwrite);
00d252cb 327
65efcfce 328/* for vpn */
d62a17ae 329extern struct ecommunity *ecommunity_new(void);
3dc339cd
DA
330extern bool ecommunity_strip(struct ecommunity *ecom, uint8_t type,
331 uint8_t subtype);
d62a17ae 332extern struct ecommunity *ecommunity_new(void);
3dc339cd
DA
333extern bool ecommunity_del_val(struct ecommunity *ecom,
334 struct ecommunity_val *eval);
dacf6ec1
PG
335struct bgp_pbr_entry_action;
336extern int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
f01e580f
PG
337 struct bgp_pbr_entry_action *api,
338 afi_t afi);
dacf6ec1 339
5b820d9e
NT
340extern void bgp_compute_aggregate_ecommunity(
341 struct bgp_aggregate *aggregate,
342 struct ecommunity *ecommunity);
4edd83f9 343
344extern void bgp_compute_aggregate_ecommunity_hash(
345 struct bgp_aggregate *aggregate,
346 struct ecommunity *ecommunity);
347extern void bgp_compute_aggregate_ecommunity_val(
348 struct bgp_aggregate *aggregate);
5b820d9e
NT
349extern void bgp_remove_ecommunity_from_aggregate(
350 struct bgp_aggregate *aggregate,
351 struct ecommunity *ecommunity);
4edd83f9 352extern void bgp_remove_ecomm_from_aggregate_hash(
353 struct bgp_aggregate *aggregate,
354 struct ecommunity *ecommunity);
5b820d9e 355extern void bgp_aggr_ecommunity_remove(void *arg);
d901dc13 356extern const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom,
357 uint32_t *bw);
7b651a32 358extern struct ecommunity *ecommunity_replace_linkbw(as_t as,
27aa23a4
DA
359 struct ecommunity *ecom,
360 uint64_t cum_bw,
361 bool disable_ieee_floating);
e8bfa90e 362
363static 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}
7b27cf7b
DA
371extern struct ecommunity *
372ecommunity_add_origin_validation_state(enum rpki_states rpki_state,
373 struct ecommunity *ecom);
c9a25614
DA
374extern struct ecommunity *ecommunity_add_node_target(struct in_addr *node_id,
375 struct ecommunity *old,
376 bool non_trans);
377extern bool ecommunity_node_target_match(struct ecommunity *ecomm,
378 struct in_addr *local_id);
00d252cb 379#endif /* _QUAGGA_BGP_ECOMMUNITY_H */