]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_pbr.c
*: auto-convert to SPDX License IDs
[mirror_frr.git] / bgpd / bgp_pbr.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * BGP pbr
4 * Copyright (C) 6WIND
5 */
6
7 #include "zebra.h"
8 #include "prefix.h"
9 #include "zclient.h"
10 #include "jhash.h"
11 #include "pbr.h"
12
13 #include "lib/printfrr.h"
14
15 #include "bgpd/bgpd.h"
16 #include "bgpd/bgp_pbr.h"
17 #include "bgpd/bgp_debug.h"
18 #include "bgpd/bgp_flowspec_util.h"
19 #include "bgpd/bgp_ecommunity.h"
20 #include "bgpd/bgp_route.h"
21 #include "bgpd/bgp_attr.h"
22 #include "bgpd/bgp_zebra.h"
23 #include "bgpd/bgp_mplsvpn.h"
24 #include "bgpd/bgp_flowspec_private.h"
25 #include "bgpd/bgp_errors.h"
26
27 DEFINE_MTYPE_STATIC(BGPD, PBR_MATCH_ENTRY, "PBR match entry");
28 DEFINE_MTYPE_STATIC(BGPD, PBR_MATCH, "PBR match");
29 DEFINE_MTYPE_STATIC(BGPD, PBR_ACTION, "PBR action");
30 DEFINE_MTYPE_STATIC(BGPD, PBR_RULE, "PBR rule");
31 DEFINE_MTYPE_STATIC(BGPD, PBR, "BGP PBR Context");
32 DEFINE_MTYPE_STATIC(BGPD, PBR_VALMASK, "BGP PBR Val Mask Value");
33
34 /* chain strings too long to fit in one line */
35 #define FSPEC_ACTION_EXCEED_LIMIT "flowspec actions exceeds limit"
36 #define IPV6_FRAGMENT_INVALID "fragment not valid for IPv6 for this implementation"
37
38 RB_GENERATE(bgp_pbr_interface_head, bgp_pbr_interface,
39 id_entry, bgp_pbr_interface_compare);
40 struct bgp_pbr_interface_head ifaces_by_name_ipv4 =
41 RB_INITIALIZER(&ifaces_by_name_ipv4);
42
43 static int bgp_pbr_match_counter_unique;
44 static int bgp_pbr_match_entry_counter_unique;
45 static int bgp_pbr_action_counter_unique;
46 static int bgp_pbr_match_iptable_counter_unique;
47
48 struct bgp_pbr_match_iptable_unique {
49 uint32_t unique;
50 struct bgp_pbr_match *bpm_found;
51 };
52
53 struct bgp_pbr_match_entry_unique {
54 uint32_t unique;
55 struct bgp_pbr_match_entry *bpme_found;
56 };
57
58 struct bgp_pbr_action_unique {
59 uint32_t unique;
60 struct bgp_pbr_action *bpa_found;
61 };
62
63 struct bgp_pbr_rule_unique {
64 uint32_t unique;
65 struct bgp_pbr_rule *bpr_found;
66 };
67
68 static int bgp_pbr_rule_walkcb(struct hash_bucket *bucket, void *arg)
69 {
70 struct bgp_pbr_rule *bpr = (struct bgp_pbr_rule *)bucket->data;
71 struct bgp_pbr_rule_unique *bpru = (struct bgp_pbr_rule_unique *)
72 arg;
73 uint32_t unique = bpru->unique;
74
75 if (bpr->unique == unique) {
76 bpru->bpr_found = bpr;
77 return HASHWALK_ABORT;
78 }
79 return HASHWALK_CONTINUE;
80 }
81
82 static int bgp_pbr_action_walkcb(struct hash_bucket *bucket, void *arg)
83 {
84 struct bgp_pbr_action *bpa = (struct bgp_pbr_action *)bucket->data;
85 struct bgp_pbr_action_unique *bpau = (struct bgp_pbr_action_unique *)
86 arg;
87 uint32_t unique = bpau->unique;
88
89 if (bpa->unique == unique) {
90 bpau->bpa_found = bpa;
91 return HASHWALK_ABORT;
92 }
93 return HASHWALK_CONTINUE;
94 }
95
96 static int bgp_pbr_match_entry_walkcb(struct hash_bucket *bucket, void *arg)
97 {
98 struct bgp_pbr_match_entry *bpme =
99 (struct bgp_pbr_match_entry *)bucket->data;
100 struct bgp_pbr_match_entry_unique *bpmeu =
101 (struct bgp_pbr_match_entry_unique *)arg;
102 uint32_t unique = bpmeu->unique;
103
104 if (bpme->unique == unique) {
105 bpmeu->bpme_found = bpme;
106 return HASHWALK_ABORT;
107 }
108 return HASHWALK_CONTINUE;
109 }
110
111 struct bgp_pbr_match_ipsetname {
112 char *ipsetname;
113 struct bgp_pbr_match *bpm_found;
114 };
115
116 static int bgp_pbr_match_pername_walkcb(struct hash_bucket *bucket, void *arg)
117 {
118 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)bucket->data;
119 struct bgp_pbr_match_ipsetname *bpmi =
120 (struct bgp_pbr_match_ipsetname *)arg;
121 char *ipset_name = bpmi->ipsetname;
122
123 if (!strncmp(ipset_name, bpm->ipset_name,
124 ZEBRA_IPSET_NAME_SIZE)) {
125 bpmi->bpm_found = bpm;
126 return HASHWALK_ABORT;
127 }
128 return HASHWALK_CONTINUE;
129 }
130
131 static int bgp_pbr_match_iptable_walkcb(struct hash_bucket *bucket, void *arg)
132 {
133 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)bucket->data;
134 struct bgp_pbr_match_iptable_unique *bpmiu =
135 (struct bgp_pbr_match_iptable_unique *)arg;
136 uint32_t unique = bpmiu->unique;
137
138 if (bpm->unique2 == unique) {
139 bpmiu->bpm_found = bpm;
140 return HASHWALK_ABORT;
141 }
142 return HASHWALK_CONTINUE;
143 }
144
145 struct bgp_pbr_match_unique {
146 uint32_t unique;
147 struct bgp_pbr_match *bpm_found;
148 };
149
150 static int bgp_pbr_match_walkcb(struct hash_bucket *bucket, void *arg)
151 {
152 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)bucket->data;
153 struct bgp_pbr_match_unique *bpmu = (struct bgp_pbr_match_unique *)
154 arg;
155 uint32_t unique = bpmu->unique;
156
157 if (bpm->unique == unique) {
158 bpmu->bpm_found = bpm;
159 return HASHWALK_ABORT;
160 }
161 return HASHWALK_CONTINUE;
162 }
163
164 static int snprintf_bgp_pbr_match_val(char *str, int len,
165 struct bgp_pbr_match_val *mval,
166 const char *prepend)
167 {
168 char *ptr = str;
169 int delta;
170
171 if (prepend) {
172 delta = snprintf(ptr, len, "%s", prepend);
173 ptr += delta;
174 len -= delta;
175 } else {
176 if (mval->unary_operator & OPERATOR_UNARY_OR) {
177 delta = snprintf(ptr, len, ", or ");
178 ptr += delta;
179 len -= delta;
180 }
181 if (mval->unary_operator & OPERATOR_UNARY_AND) {
182 delta = snprintf(ptr, len, ", and ");
183 ptr += delta;
184 len -= delta;
185 }
186 }
187 if (mval->compare_operator & OPERATOR_COMPARE_LESS_THAN) {
188 delta = snprintf(ptr, len, "<");
189 ptr += delta;
190 len -= delta;
191 }
192 if (mval->compare_operator & OPERATOR_COMPARE_GREATER_THAN) {
193 delta = snprintf(ptr, len, ">");
194 ptr += delta;
195 len -= delta;
196 }
197 if (mval->compare_operator & OPERATOR_COMPARE_EQUAL_TO) {
198 delta = snprintf(ptr, len, "=");
199 ptr += delta;
200 len -= delta;
201 }
202 if (mval->compare_operator & OPERATOR_COMPARE_EXACT_MATCH) {
203 delta = snprintf(ptr, len, "match");
204 ptr += delta;
205 len -= delta;
206 }
207 ptr += snprintf(ptr, len, " %u", mval->value);
208 return (int)(ptr - str);
209 }
210
211 #define INCREMENT_DISPLAY(_ptr, _cnt, _len) do { \
212 int sn_delta; \
213 \
214 if (_cnt) { \
215 sn_delta = snprintf((_ptr), (_len), "; ");\
216 (_len) -= sn_delta; \
217 (_ptr) += sn_delta; \
218 } \
219 (_cnt)++; \
220 } while (0)
221
222 /* this structure can be used for port range,
223 * but also for other values range like packet length range
224 */
225 struct bgp_pbr_range_port {
226 uint16_t min_port;
227 uint16_t max_port;
228 };
229
230 /* this structure can be used to filter with a mask
231 * for instance it supports not instructions like for
232 * tcpflags
233 */
234 struct bgp_pbr_val_mask {
235 uint16_t val;
236 uint16_t mask;
237 };
238
239 /* this structure is used to pass instructs
240 * so that BGP can create pbr instructions to ZEBRA
241 */
242 struct bgp_pbr_filter {
243 uint8_t type;
244 vrf_id_t vrf_id;
245 uint8_t family;
246 struct prefix *src;
247 struct prefix *dst;
248 uint8_t bitmask_iprule;
249 uint8_t protocol;
250 struct bgp_pbr_range_port *pkt_len;
251 struct bgp_pbr_range_port *src_port;
252 struct bgp_pbr_range_port *dst_port;
253 struct bgp_pbr_val_mask *tcp_flags;
254 struct bgp_pbr_val_mask *dscp;
255 struct bgp_pbr_val_mask *flow_label;
256 struct bgp_pbr_val_mask *pkt_len_val;
257 struct bgp_pbr_val_mask *fragment;
258 };
259
260 /* this structure is used to contain OR instructions
261 * so that BGP can create multiple pbr instructions
262 * to ZEBRA
263 */
264 struct bgp_pbr_or_filter {
265 struct list *tcpflags;
266 struct list *dscp;
267 struct list *flowlabel;
268 struct list *pkt_len;
269 struct list *fragment;
270 struct list *icmp_type;
271 struct list *icmp_code;
272 };
273
274 static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
275 struct bgp_path_info *path,
276 struct bgp_pbr_filter *bpf,
277 struct nexthop *nh,
278 float *rate);
279
280 static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add);
281
282 static bool bgp_pbr_extract_enumerate_unary_opposite(
283 uint8_t unary_operator,
284 struct bgp_pbr_val_mask *and_valmask,
285 struct list *or_valmask, uint32_t value,
286 uint8_t type_entry)
287 {
288 if (unary_operator == OPERATOR_UNARY_AND && and_valmask) {
289 if (type_entry == FLOWSPEC_TCP_FLAGS) {
290 and_valmask->mask |=
291 TCP_HEADER_ALL_FLAGS &
292 ~(value);
293 } else if (type_entry == FLOWSPEC_DSCP ||
294 type_entry == FLOWSPEC_FLOW_LABEL ||
295 type_entry == FLOWSPEC_PKT_LEN ||
296 type_entry == FLOWSPEC_FRAGMENT) {
297 and_valmask->val = value;
298 and_valmask->mask = 1; /* inverse */
299 }
300 } else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) {
301 and_valmask = XCALLOC(MTYPE_PBR_VALMASK,
302 sizeof(struct bgp_pbr_val_mask));
303 if (type_entry == FLOWSPEC_TCP_FLAGS) {
304 and_valmask->val = TCP_HEADER_ALL_FLAGS;
305 and_valmask->mask |=
306 TCP_HEADER_ALL_FLAGS &
307 ~(value);
308 } else if (type_entry == FLOWSPEC_DSCP ||
309 type_entry == FLOWSPEC_FLOW_LABEL ||
310 type_entry == FLOWSPEC_FRAGMENT ||
311 type_entry == FLOWSPEC_PKT_LEN) {
312 and_valmask->val = value;
313 and_valmask->mask = 1; /* inverse */
314 }
315 listnode_add(or_valmask, and_valmask);
316 } else if (type_entry == FLOWSPEC_ICMP_CODE ||
317 type_entry == FLOWSPEC_ICMP_TYPE)
318 return false;
319 return true;
320 }
321
322 /* TCP : FIN and SYN -> val = ALL; mask = 3
323 * TCP : not (FIN and SYN) -> val = ALL; mask = ALL & ~(FIN|RST)
324 * other variables type: dscp, pkt len, fragment, flow label
325 * - value is copied in bgp_pbr_val_mask->val value
326 * - if negate form is identifierd, bgp_pbr_val_mask->mask set to 1
327 */
328 static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
329 int num, uint8_t unary_operator,
330 void *valmask, uint8_t type_entry)
331 {
332 int i = 0;
333 struct bgp_pbr_val_mask *and_valmask = NULL;
334 struct list *or_valmask = NULL;
335 bool ret;
336
337 if (valmask) {
338 if (unary_operator == OPERATOR_UNARY_AND) {
339 and_valmask = (struct bgp_pbr_val_mask *)valmask;
340 memset(and_valmask, 0, sizeof(struct bgp_pbr_val_mask));
341 } else if (unary_operator == OPERATOR_UNARY_OR) {
342 or_valmask = (struct list *)valmask;
343 }
344 }
345 for (i = 0; i < num; i++) {
346 if (i != 0 && list[i].unary_operator !=
347 unary_operator)
348 return false;
349 if (!(list[i].compare_operator &
350 OPERATOR_COMPARE_EQUAL_TO) &&
351 !(list[i].compare_operator &
352 OPERATOR_COMPARE_EXACT_MATCH)) {
353 if ((list[i].compare_operator &
354 OPERATOR_COMPARE_LESS_THAN) &&
355 (list[i].compare_operator &
356 OPERATOR_COMPARE_GREATER_THAN)) {
357 ret = bgp_pbr_extract_enumerate_unary_opposite(
358 unary_operator, and_valmask,
359 or_valmask, list[i].value,
360 type_entry);
361 if (!ret)
362 return ret;
363 continue;
364 }
365 return false;
366 }
367 if (unary_operator == OPERATOR_UNARY_AND && and_valmask) {
368 if (type_entry == FLOWSPEC_TCP_FLAGS)
369 and_valmask->mask |=
370 TCP_HEADER_ALL_FLAGS & list[i].value;
371 } else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) {
372 and_valmask = XCALLOC(MTYPE_PBR_VALMASK,
373 sizeof(struct bgp_pbr_val_mask));
374 if (type_entry == FLOWSPEC_TCP_FLAGS) {
375 and_valmask->val = TCP_HEADER_ALL_FLAGS;
376 and_valmask->mask |=
377 TCP_HEADER_ALL_FLAGS & list[i].value;
378 } else if (type_entry == FLOWSPEC_DSCP ||
379 type_entry == FLOWSPEC_FLOW_LABEL ||
380 type_entry == FLOWSPEC_ICMP_TYPE ||
381 type_entry == FLOWSPEC_ICMP_CODE ||
382 type_entry == FLOWSPEC_FRAGMENT ||
383 type_entry == FLOWSPEC_PKT_LEN)
384 and_valmask->val = list[i].value;
385 listnode_add(or_valmask, and_valmask);
386 }
387 }
388 if (unary_operator == OPERATOR_UNARY_AND && and_valmask
389 && type_entry == FLOWSPEC_TCP_FLAGS)
390 and_valmask->val = TCP_HEADER_ALL_FLAGS;
391 return true;
392 }
393
394 /* if unary operator can either be UNARY_OR/AND/OR-AND.
395 * in the latter case, combinationf of both is not handled
396 */
397 static bool bgp_pbr_extract_enumerate(struct bgp_pbr_match_val list[],
398 int num, uint8_t unary_operator,
399 void *valmask, uint8_t type_entry)
400 {
401 bool ret;
402 uint8_t unary_operator_val;
403 bool double_check = false;
404
405 if ((unary_operator & OPERATOR_UNARY_OR) &&
406 (unary_operator & OPERATOR_UNARY_AND)) {
407 unary_operator_val = OPERATOR_UNARY_AND;
408 double_check = true;
409 } else
410 unary_operator_val = unary_operator;
411 ret = bgp_pbr_extract_enumerate_unary(list, num, unary_operator_val,
412 valmask, type_entry);
413 if (!ret && double_check)
414 ret = bgp_pbr_extract_enumerate_unary(list, num,
415 OPERATOR_UNARY_OR,
416 valmask,
417 type_entry);
418 return ret;
419 }
420
421 /* returns the unary operator that is in the list
422 * return 0 if both operators are used
423 */
424 static uint8_t bgp_pbr_match_val_get_operator(struct bgp_pbr_match_val list[],
425 int num)
426
427 {
428 int i;
429 uint8_t unary_operator = OPERATOR_UNARY_AND;
430
431 for (i = 0; i < num; i++) {
432 if (i == 0)
433 continue;
434 if (list[i].unary_operator & OPERATOR_UNARY_OR)
435 unary_operator = OPERATOR_UNARY_OR;
436 if ((list[i].unary_operator & OPERATOR_UNARY_AND
437 && unary_operator == OPERATOR_UNARY_OR) ||
438 (list[i].unary_operator & OPERATOR_UNARY_OR
439 && unary_operator == OPERATOR_UNARY_AND))
440 return 0;
441 }
442 return unary_operator;
443 }
444
445
446 /* return true if extraction ok
447 */
448 static bool bgp_pbr_extract(struct bgp_pbr_match_val list[],
449 int num,
450 struct bgp_pbr_range_port *range)
451 {
452 int i = 0;
453 bool exact_match = false;
454
455 if (range)
456 memset(range, 0, sizeof(struct bgp_pbr_range_port));
457
458 if (num > 2)
459 return false;
460 for (i = 0; i < num; i++) {
461 if (i != 0 && (list[i].compare_operator ==
462 OPERATOR_COMPARE_EQUAL_TO))
463 return false;
464 if (i == 0 && (list[i].compare_operator ==
465 OPERATOR_COMPARE_EQUAL_TO)) {
466 if (range)
467 range->min_port = list[i].value;
468 exact_match = true;
469 }
470 if (exact_match && i > 0)
471 return false;
472 if (list[i].compare_operator ==
473 (OPERATOR_COMPARE_GREATER_THAN +
474 OPERATOR_COMPARE_EQUAL_TO)) {
475 if (range)
476 range->min_port = list[i].value;
477 } else if (list[i].compare_operator ==
478 (OPERATOR_COMPARE_LESS_THAN +
479 OPERATOR_COMPARE_EQUAL_TO)) {
480 if (range)
481 range->max_port = list[i].value;
482 } else if (list[i].compare_operator ==
483 OPERATOR_COMPARE_LESS_THAN) {
484 if (range)
485 range->max_port = list[i].value - 1;
486 } else if (list[i].compare_operator ==
487 OPERATOR_COMPARE_GREATER_THAN) {
488 if (range)
489 range->min_port = list[i].value + 1;
490 }
491 }
492 return true;
493 }
494
495 static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
496 {
497 bool enumerate_icmp = false;
498
499 if (api->type == BGP_PBR_UNDEFINED) {
500 if (BGP_DEBUG(pbr, PBR))
501 zlog_debug("BGP: pbr entry undefined. cancel.");
502 return 0;
503 }
504 /* because bgp pbr entry may contain unsupported
505 * combinations, a message will be displayed here if
506 * not supported.
507 * for now, only match/set supported is
508 * - combination src/dst => redirect nexthop [ + rate]
509 * - combination src/dst => redirect VRF [ + rate]
510 * - combination src/dst => drop
511 * - combination srcport + @IP
512 */
513 if (api->match_protocol_num > 1) {
514 if (BGP_DEBUG(pbr, PBR))
515 zlog_debug("BGP: match protocol operations:multiple protocols ( %d). ignoring.",
516 api->match_protocol_num);
517 return 0;
518 }
519 if (api->src_prefix_offset > 0 ||
520 api->dst_prefix_offset > 0) {
521 if (BGP_DEBUG(pbr, PBR))
522 zlog_debug("BGP: match prefix offset:"
523 "implementation does not support it.");
524 return 0;
525 }
526 if (api->match_protocol_num == 1 &&
527 api->protocol[0].value != PROTOCOL_UDP &&
528 api->protocol[0].value != PROTOCOL_ICMP &&
529 api->protocol[0].value != PROTOCOL_ICMPV6 &&
530 api->protocol[0].value != PROTOCOL_TCP) {
531 if (BGP_DEBUG(pbr, PBR))
532 zlog_debug("BGP: match protocol operations:protocol (%d) not supported. ignoring",
533 api->match_protocol_num);
534 return 0;
535 }
536 if (!bgp_pbr_extract(api->src_port, api->match_src_port_num, NULL)) {
537 if (BGP_DEBUG(pbr, PBR))
538 zlog_debug("BGP: match src port operations:too complex. ignoring.");
539 return 0;
540 }
541 if (!bgp_pbr_extract(api->dst_port, api->match_dst_port_num, NULL)) {
542 if (BGP_DEBUG(pbr, PBR))
543 zlog_debug("BGP: match dst port operations:too complex. ignoring.");
544 return 0;
545 }
546 if (!bgp_pbr_extract_enumerate(api->tcpflags,
547 api->match_tcpflags_num,
548 OPERATOR_UNARY_AND |
549 OPERATOR_UNARY_OR, NULL,
550 FLOWSPEC_TCP_FLAGS)) {
551 if (BGP_DEBUG(pbr, PBR))
552 zlog_debug("BGP: match tcp flags:too complex. ignoring.");
553 return 0;
554 }
555 if (!bgp_pbr_extract(api->icmp_type, api->match_icmp_type_num, NULL)) {
556 if (!bgp_pbr_extract_enumerate(api->icmp_type,
557 api->match_icmp_type_num,
558 OPERATOR_UNARY_OR, NULL,
559 FLOWSPEC_ICMP_TYPE)) {
560 if (BGP_DEBUG(pbr, PBR))
561 zlog_debug("BGP: match icmp type operations:too complex. ignoring.");
562 return 0;
563 }
564 enumerate_icmp = true;
565 }
566 if (!bgp_pbr_extract(api->icmp_code, api->match_icmp_code_num, NULL)) {
567 if (!bgp_pbr_extract_enumerate(api->icmp_code,
568 api->match_icmp_code_num,
569 OPERATOR_UNARY_OR, NULL,
570 FLOWSPEC_ICMP_CODE)) {
571 if (BGP_DEBUG(pbr, PBR))
572 zlog_debug("BGP: match icmp code operations:too complex. ignoring.");
573 return 0;
574 } else if (api->match_icmp_type_num > 1 &&
575 !enumerate_icmp) {
576 if (BGP_DEBUG(pbr, PBR))
577 zlog_debug("BGP: match icmp code is enumerate, and icmp type is not. too complex. ignoring.");
578 return 0;
579 }
580 }
581 if (!bgp_pbr_extract(api->port, api->match_port_num, NULL)) {
582 if (BGP_DEBUG(pbr, PBR))
583 zlog_debug("BGP: match port operations:too complex. ignoring.");
584 return 0;
585 }
586 if (api->match_packet_length_num) {
587 bool ret;
588
589 ret = bgp_pbr_extract(api->packet_length,
590 api->match_packet_length_num, NULL);
591 if (!ret)
592 ret = bgp_pbr_extract_enumerate(api->packet_length,
593 api->match_packet_length_num,
594 OPERATOR_UNARY_OR
595 | OPERATOR_UNARY_AND,
596 NULL, FLOWSPEC_PKT_LEN);
597 if (!ret) {
598 if (BGP_DEBUG(pbr, PBR))
599 zlog_debug("BGP: match packet length operations:too complex. ignoring.");
600 return 0;
601 }
602 }
603 if (api->match_dscp_num) {
604 if (!bgp_pbr_extract_enumerate(api->dscp, api->match_dscp_num,
605 OPERATOR_UNARY_OR | OPERATOR_UNARY_AND,
606 NULL, FLOWSPEC_DSCP)) {
607 if (BGP_DEBUG(pbr, PBR))
608 zlog_debug("BGP: match DSCP operations:too complex. ignoring.");
609 return 0;
610 }
611 }
612 if (api->match_flowlabel_num) {
613 if (api->afi == AFI_IP) {
614 if (BGP_DEBUG(pbr, PBR))
615 zlog_debug("BGP: match Flow Label operations:"
616 "Not for IPv4.");
617 return 0;
618 }
619 if (!bgp_pbr_extract_enumerate(api->flow_label,
620 api->match_flowlabel_num,
621 OPERATOR_UNARY_OR | OPERATOR_UNARY_AND,
622 NULL, FLOWSPEC_FLOW_LABEL)) {
623 if (BGP_DEBUG(pbr, PBR))
624 zlog_debug("BGP: match FlowLabel operations:"
625 "too complex. ignoring.");
626 return 0;
627 }
628 if (BGP_DEBUG(pbr, PBR))
629 zlog_debug("BGP: match FlowLabel operations "
630 "not supported. ignoring.");
631 return 0;
632 }
633 if (api->match_fragment_num) {
634 char fail_str[64];
635 bool success;
636
637 success = bgp_pbr_extract_enumerate(api->fragment,
638 api->match_fragment_num,
639 OPERATOR_UNARY_OR
640 | OPERATOR_UNARY_AND,
641 NULL, FLOWSPEC_FRAGMENT);
642 if (success) {
643 int i;
644
645 for (i = 0; i < api->match_fragment_num; i++) {
646 if (api->fragment[i].value != 1 &&
647 api->fragment[i].value != 2 &&
648 api->fragment[i].value != 4 &&
649 api->fragment[i].value != 8) {
650 success = false;
651 snprintf(
652 fail_str, sizeof(fail_str),
653 "Value not valid (%d) for this implementation",
654 api->fragment[i].value);
655 }
656 if (api->afi == AFI_IP6 &&
657 api->fragment[i].value == 1) {
658 success = false;
659 snprintf(fail_str, sizeof(fail_str),
660 "IPv6 dont fragment match invalid (%d)",
661 api->fragment[i].value);
662 }
663 }
664 if (api->afi == AFI_IP6) {
665 success = false;
666 snprintf(fail_str, sizeof(fail_str),
667 "%s", IPV6_FRAGMENT_INVALID);
668 }
669 } else
670 snprintf(fail_str, sizeof(fail_str),
671 "too complex. ignoring");
672 if (!success) {
673 if (BGP_DEBUG(pbr, PBR))
674 zlog_debug("BGP: match fragment operation (%d) %s",
675 api->match_fragment_num,
676 fail_str);
677 return 0;
678 }
679 }
680
681 /* no combinations with both src_port and dst_port
682 * or port with src_port and dst_port
683 */
684 if (api->match_src_port_num + api->match_dst_port_num +
685 api->match_port_num > 3) {
686 if (BGP_DEBUG(pbr, PBR))
687 zlog_debug("BGP: match multiple port operations: too complex. ignoring.");
688 return 0;
689 }
690 if ((api->match_src_port_num || api->match_dst_port_num
691 || api->match_port_num) && (api->match_icmp_type_num
692 || api->match_icmp_code_num)) {
693 if (BGP_DEBUG(pbr, PBR))
694 zlog_debug("BGP: match multiple port/imcp operations: too complex. ignoring.");
695 return 0;
696 }
697 /* iprule only supports redirect IP */
698 if (api->type == BGP_PBR_IPRULE) {
699 int i;
700
701 for (i = 0; i < api->action_num; i++) {
702 if (api->actions[i].action == ACTION_TRAFFICRATE &&
703 api->actions[i].u.r.rate == 0) {
704 if (BGP_DEBUG(pbr, PBR)) {
705 bgp_pbr_print_policy_route(api);
706 zlog_debug("BGP: iprule match actions drop not supported");
707 }
708 return 0;
709 }
710 if (api->actions[i].action == ACTION_MARKING) {
711 if (BGP_DEBUG(pbr, PBR)) {
712 bgp_pbr_print_policy_route(api);
713 zlog_warn("PBR: iprule set DSCP/Flow Label %u not supported",
714 api->actions[i].u.marking_dscp);
715 }
716 }
717 if (api->actions[i].action == ACTION_REDIRECT) {
718 if (BGP_DEBUG(pbr, PBR)) {
719 bgp_pbr_print_policy_route(api);
720 zlog_warn("PBR: iprule redirect VRF %u not supported",
721 api->actions[i].u.redirect_vrf);
722 }
723 }
724 }
725
726 } else if (!(api->match_bitmask & PREFIX_SRC_PRESENT) &&
727 !(api->match_bitmask & PREFIX_DST_PRESENT)) {
728 if (BGP_DEBUG(pbr, PBR)) {
729 bgp_pbr_print_policy_route(api);
730 zlog_debug("BGP: match actions without src or dst address can not operate. ignoring.");
731 }
732 return 0;
733 }
734 return 1;
735 }
736
737 /* return -1 if build or validation failed */
738
739 int bgp_pbr_build_and_validate_entry(const struct prefix *p,
740 struct bgp_path_info *path,
741 struct bgp_pbr_entry_main *api)
742 {
743 int ret;
744 uint32_t i, action_count = 0;
745 struct ecommunity *ecom;
746 struct ecommunity_val *ecom_eval;
747 struct bgp_pbr_entry_action *api_action;
748 struct prefix *src = NULL, *dst = NULL;
749 int valid_prefix = 0;
750 struct bgp_pbr_entry_action *api_action_redirect_ip = NULL;
751 bool discard_action_found = false;
752 afi_t afi = family2afi(p->u.prefix_flowspec.family);
753
754 /* extract match from flowspec entries */
755 ret = bgp_flowspec_match_rules_fill((uint8_t *)p->u.prefix_flowspec.ptr,
756 p->u.prefix_flowspec.prefixlen, api, afi);
757 if (ret < 0)
758 return -1;
759 /* extract actiosn from flowspec ecom list */
760 if (path && bgp_attr_get_ecommunity(path->attr)) {
761 ecom = bgp_attr_get_ecommunity(path->attr);
762 for (i = 0; i < ecom->size; i++) {
763 ecom_eval = (struct ecommunity_val *)
764 (ecom->val + (i * ECOMMUNITY_SIZE));
765 action_count++;
766 if (action_count > ACTIONS_MAX_NUM) {
767 if (BGP_DEBUG(pbr, PBR_ERROR))
768 flog_err(
769 EC_BGP_FLOWSPEC_PACKET,
770 "%s: %s (max %u)",
771 __func__,
772 FSPEC_ACTION_EXCEED_LIMIT,
773 action_count);
774 break;
775 }
776 api_action = &api->actions[action_count - 1];
777
778 if ((ecom_eval->val[1] ==
779 (char)ECOMMUNITY_REDIRECT_VRF) &&
780 (ecom_eval->val[0] ==
781 (char)ECOMMUNITY_ENCODE_TRANS_EXP ||
782 ecom_eval->val[0] ==
783 (char)ECOMMUNITY_EXTENDED_COMMUNITY_PART_2 ||
784 ecom_eval->val[0] ==
785 (char)ECOMMUNITY_EXTENDED_COMMUNITY_PART_3)) {
786 struct ecommunity *eckey = ecommunity_new();
787 struct ecommunity_val ecom_copy;
788
789 memcpy(&ecom_copy, ecom_eval,
790 sizeof(struct ecommunity_val));
791 ecom_copy.val[0] &=
792 ~ECOMMUNITY_ENCODE_TRANS_EXP;
793 ecom_copy.val[1] = ECOMMUNITY_ROUTE_TARGET;
794 ecommunity_add_val(eckey, &ecom_copy,
795 false, false);
796
797 api_action->action = ACTION_REDIRECT;
798 api_action->u.redirect_vrf =
799 get_first_vrf_for_redirect_with_rt(
800 eckey);
801 ecommunity_free(&eckey);
802 } else if ((ecom_eval->val[0] ==
803 (char)ECOMMUNITY_ENCODE_REDIRECT_IP_NH) &&
804 (ecom_eval->val[1] ==
805 (char)ECOMMUNITY_REDIRECT_IP_NH)) {
806 /* in case the 2 ecom present,
807 * do not overwrite
808 * draft-ietf-idr-flowspec-redirect
809 */
810 if (api_action_redirect_ip &&
811 p->u.prefix_flowspec.family == AF_INET) {
812 if (api_action_redirect_ip->u
813 .zr.redirect_ip_v4.s_addr
814 != INADDR_ANY)
815 continue;
816 if (path->attr->nexthop.s_addr
817 == INADDR_ANY)
818 continue;
819 api_action_redirect_ip->u.zr
820 .redirect_ip_v4.s_addr =
821 path->attr->nexthop.s_addr;
822 api_action_redirect_ip->u.zr.duplicate
823 = ecom_eval->val[7];
824 continue;
825 } else if (api_action_redirect_ip &&
826 p->u.prefix_flowspec.family == AF_INET6) {
827 if (memcmp(&api_action_redirect_ip->u
828 .zr.redirect_ip_v6,
829 &in6addr_any,
830 sizeof(struct in6_addr)))
831 continue;
832 if (path->attr->mp_nexthop_len == 0 ||
833 path->attr->mp_nexthop_len ==
834 BGP_ATTR_NHLEN_IPV4 ||
835 path->attr->mp_nexthop_len ==
836 BGP_ATTR_NHLEN_VPNV4)
837 continue;
838 memcpy(&api_action_redirect_ip->u
839 .zr.redirect_ip_v6,
840 &path->attr->mp_nexthop_global,
841 sizeof(struct in6_addr));
842 api_action_redirect_ip->u.zr.duplicate
843 = ecom_eval->val[7];
844 continue;
845 } else if (p->u.prefix_flowspec.family ==
846 AF_INET) {
847 api_action->action = ACTION_REDIRECT_IP;
848 api_action->u.zr.redirect_ip_v4.s_addr =
849 path->attr->nexthop.s_addr;
850 api_action->u.zr.duplicate =
851 ecom_eval->val[7];
852 api_action_redirect_ip = api_action;
853 } else if (p->u.prefix_flowspec.family ==
854 AF_INET6) {
855 api_action->action = ACTION_REDIRECT_IP;
856 memcpy(&api_action->u
857 .zr.redirect_ip_v6,
858 &path->attr->mp_nexthop_global,
859 sizeof(struct in6_addr));
860 api_action->u.zr.duplicate
861 = ecom_eval->val[7];
862 api_action_redirect_ip = api_action;
863 }
864 } else if ((ecom_eval->val[0] ==
865 (char)ECOMMUNITY_ENCODE_IP) &&
866 (ecom_eval->val[1] ==
867 (char)ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4)) {
868 /* in case the 2 ecom present,
869 * overwrite simpson draft
870 * update redirect ip fields
871 */
872 if (api_action_redirect_ip) {
873 memcpy(&(api_action_redirect_ip->u
874 .zr.redirect_ip_v4.s_addr),
875 (ecom_eval->val+2), 4);
876 api_action_redirect_ip->u
877 .zr.duplicate =
878 ecom_eval->val[7];
879 continue;
880 } else {
881 api_action->action = ACTION_REDIRECT_IP;
882 memcpy(&(api_action->u
883 .zr.redirect_ip_v4.s_addr),
884 (ecom_eval->val+2), 4);
885 api_action->u.zr.duplicate =
886 ecom_eval->val[7];
887 api_action_redirect_ip = api_action;
888 }
889 } else {
890 if (ecom_eval->val[0] !=
891 (char)ECOMMUNITY_ENCODE_TRANS_EXP)
892 continue;
893 ret = ecommunity_fill_pbr_action(ecom_eval,
894 api_action,
895 afi);
896 if (ret != 0)
897 continue;
898 if ((api_action->action == ACTION_TRAFFICRATE)
899 && api->actions[i].u.r.rate == 0)
900 discard_action_found = true;
901 }
902 api->action_num++;
903 }
904 }
905 if (path && path->attr && bgp_attr_get_ipv6_ecommunity(path->attr)) {
906 struct ecommunity_val_ipv6 *ipv6_ecom_eval;
907
908 ecom = bgp_attr_get_ipv6_ecommunity(path->attr);
909 for (i = 0; i < ecom->size; i++) {
910 ipv6_ecom_eval = (struct ecommunity_val_ipv6 *)
911 (ecom->val + (i * ecom->unit_size));
912 action_count++;
913 if (action_count > ACTIONS_MAX_NUM) {
914 if (BGP_DEBUG(pbr, PBR_ERROR))
915 flog_err(
916 EC_BGP_FLOWSPEC_PACKET,
917 "%s: flowspec actions exceeds limit (max %u)",
918 __func__, action_count);
919 break;
920 }
921 api_action = &api->actions[action_count - 1];
922 if ((ipv6_ecom_eval->val[1] ==
923 (char)ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6) &&
924 (ipv6_ecom_eval->val[0] ==
925 (char)ECOMMUNITY_ENCODE_TRANS_EXP)) {
926 struct ecommunity *eckey = ecommunity_new();
927 struct ecommunity_val_ipv6 ecom_copy;
928
929 eckey->unit_size = IPV6_ECOMMUNITY_SIZE;
930 memcpy(&ecom_copy, ipv6_ecom_eval,
931 sizeof(struct ecommunity_val_ipv6));
932 ecom_copy.val[1] = ECOMMUNITY_ROUTE_TARGET;
933 ecommunity_add_val_ipv6(eckey, &ecom_copy,
934 false, false);
935 api_action->action = ACTION_REDIRECT;
936 api_action->u.redirect_vrf =
937 get_first_vrf_for_redirect_with_rt(
938 eckey);
939 ecommunity_free(&eckey);
940 api->action_num++;
941 }
942 }
943 }
944 /* if ECOMMUNITY_TRAFFIC_RATE = 0 as action
945 * then reduce the API action list to that action
946 */
947 if (api->action_num > 1 && discard_action_found) {
948 api->action_num = 1;
949 memset(&api->actions[0], 0,
950 sizeof(struct bgp_pbr_entry_action));
951 api->actions[0].action = ACTION_TRAFFICRATE;
952 }
953
954 /* validate if incoming matc/action is compatible
955 * with our policy routing engine
956 */
957 if (!bgp_pbr_validate_policy_route(api))
958 return -1;
959
960 /* check inconsistency in the match rule */
961 if (api->match_bitmask & PREFIX_SRC_PRESENT) {
962 src = &api->src_prefix;
963 afi = family2afi(src->family);
964 valid_prefix = 1;
965 }
966 if (api->match_bitmask & PREFIX_DST_PRESENT) {
967 dst = &api->dst_prefix;
968 if (valid_prefix && afi != family2afi(dst->family)) {
969 if (BGP_DEBUG(pbr, PBR)) {
970 bgp_pbr_print_policy_route(api);
971 zlog_debug("%s: inconsistency: no match for afi src and dst (%u/%u)",
972 __func__, afi, family2afi(dst->family));
973 }
974 return -1;
975 }
976 }
977 return 0;
978 }
979
980 static void bgp_pbr_match_entry_free(void *arg)
981 {
982 struct bgp_pbr_match_entry *bpme;
983
984 bpme = (struct bgp_pbr_match_entry *)arg;
985
986 if (bpme->installed) {
987 bgp_send_pbr_ipset_entry_match(bpme, false);
988 bpme->installed = false;
989 bpme->backpointer = NULL;
990 }
991 XFREE(MTYPE_PBR_MATCH_ENTRY, bpme);
992 }
993
994 static void bgp_pbr_match_free(void *arg)
995 {
996 struct bgp_pbr_match *bpm;
997
998 bpm = (struct bgp_pbr_match *)arg;
999
1000 hash_clean(bpm->entry_hash, bgp_pbr_match_entry_free);
1001
1002 if (hashcount(bpm->entry_hash) == 0) {
1003 /* delete iptable entry first */
1004 /* then delete ipset match */
1005 if (bpm->installed) {
1006 if (bpm->installed_in_iptable) {
1007 bgp_send_pbr_iptable(bpm->action,
1008 bpm, false);
1009 bpm->installed_in_iptable = false;
1010 bpm->action->refcnt--;
1011 }
1012 bgp_send_pbr_ipset_match(bpm, false);
1013 bpm->installed = false;
1014 bpm->action = NULL;
1015 }
1016 }
1017 hash_free(bpm->entry_hash);
1018
1019 XFREE(MTYPE_PBR_MATCH, bpm);
1020 }
1021
1022 static void *bgp_pbr_match_alloc_intern(void *arg)
1023 {
1024 struct bgp_pbr_match *bpm, *new;
1025
1026 bpm = (struct bgp_pbr_match *)arg;
1027
1028 new = XCALLOC(MTYPE_PBR_MATCH, sizeof(*new));
1029 memcpy(new, bpm, sizeof(*bpm));
1030
1031 return new;
1032 }
1033
1034 static void bgp_pbr_rule_free(void *arg)
1035 {
1036 struct bgp_pbr_rule *bpr;
1037
1038 bpr = (struct bgp_pbr_rule *)arg;
1039
1040 /* delete iprule */
1041 if (bpr->installed) {
1042 bgp_send_pbr_rule_action(bpr->action, bpr, false);
1043 bpr->installed = false;
1044 bpr->action->refcnt--;
1045 bpr->action = NULL;
1046 }
1047 XFREE(MTYPE_PBR_RULE, bpr);
1048 }
1049
1050 static void *bgp_pbr_rule_alloc_intern(void *arg)
1051 {
1052 struct bgp_pbr_rule *bpr, *new;
1053
1054 bpr = (struct bgp_pbr_rule *)arg;
1055
1056 new = XCALLOC(MTYPE_PBR_RULE, sizeof(*new));
1057 memcpy(new, bpr, sizeof(*bpr));
1058
1059 return new;
1060 }
1061
1062 static void bgp_pbr_bpa_remove(struct bgp_pbr_action *bpa)
1063 {
1064 if ((bpa->refcnt == 0) && bpa->installed && bpa->table_id != 0) {
1065 bgp_send_pbr_rule_action(bpa, NULL, false);
1066 bgp_zebra_announce_default(bpa->bgp, &bpa->nh, bpa->afi,
1067 bpa->table_id, false);
1068 bpa->installed = false;
1069 }
1070 }
1071
1072 static void bgp_pbr_bpa_add(struct bgp_pbr_action *bpa)
1073 {
1074 if (!bpa->installed && !bpa->install_in_progress) {
1075 bgp_send_pbr_rule_action(bpa, NULL, true);
1076 bgp_zebra_announce_default(bpa->bgp, &bpa->nh, bpa->afi,
1077 bpa->table_id, true);
1078 }
1079 }
1080
1081 static void bgp_pbr_action_free(void *arg)
1082 {
1083 struct bgp_pbr_action *bpa = arg;
1084
1085 bgp_pbr_bpa_remove(bpa);
1086
1087 XFREE(MTYPE_PBR_ACTION, bpa);
1088 }
1089
1090 static void *bgp_pbr_action_alloc_intern(void *arg)
1091 {
1092 struct bgp_pbr_action *bpa, *new;
1093
1094 bpa = (struct bgp_pbr_action *)arg;
1095
1096 new = XCALLOC(MTYPE_PBR_ACTION, sizeof(*new));
1097
1098 memcpy(new, bpa, sizeof(*bpa));
1099
1100 return new;
1101 }
1102
1103 static void *bgp_pbr_match_entry_alloc_intern(void *arg)
1104 {
1105 struct bgp_pbr_match_entry *bpme, *new;
1106
1107 bpme = (struct bgp_pbr_match_entry *)arg;
1108
1109 new = XCALLOC(MTYPE_PBR_MATCH_ENTRY, sizeof(*new));
1110
1111 memcpy(new, bpme, sizeof(*bpme));
1112
1113 return new;
1114 }
1115
1116 uint32_t bgp_pbr_match_hash_key(const void *arg)
1117 {
1118 const struct bgp_pbr_match *pbm = arg;
1119 uint32_t key;
1120
1121 key = jhash_1word(pbm->vrf_id, 0x4312abde);
1122 key = jhash_1word(pbm->flags, key);
1123 key = jhash_1word(pbm->family, key);
1124 key = jhash(&pbm->pkt_len_min, 2, key);
1125 key = jhash(&pbm->pkt_len_max, 2, key);
1126 key = jhash(&pbm->tcp_flags, 2, key);
1127 key = jhash(&pbm->tcp_mask_flags, 2, key);
1128 key = jhash(&pbm->dscp_value, 1, key);
1129 key = jhash(&pbm->flow_label, 2, key);
1130 key = jhash(&pbm->fragment, 1, key);
1131 key = jhash(&pbm->protocol, 1, key);
1132 return jhash_1word(pbm->type, key);
1133 }
1134
1135 bool bgp_pbr_match_hash_equal(const void *arg1, const void *arg2)
1136 {
1137 const struct bgp_pbr_match *r1, *r2;
1138
1139 r1 = (const struct bgp_pbr_match *)arg1;
1140 r2 = (const struct bgp_pbr_match *)arg2;
1141
1142 if (r1->vrf_id != r2->vrf_id)
1143 return false;
1144
1145 if (r1->family != r2->family)
1146 return false;
1147
1148 if (r1->type != r2->type)
1149 return false;
1150
1151 if (r1->flags != r2->flags)
1152 return false;
1153
1154 if (r1->action != r2->action)
1155 return false;
1156
1157 if (r1->pkt_len_min != r2->pkt_len_min)
1158 return false;
1159
1160 if (r1->pkt_len_max != r2->pkt_len_max)
1161 return false;
1162
1163 if (r1->tcp_flags != r2->tcp_flags)
1164 return false;
1165
1166 if (r1->tcp_mask_flags != r2->tcp_mask_flags)
1167 return false;
1168
1169 if (r1->dscp_value != r2->dscp_value)
1170 return false;
1171
1172 if (r1->flow_label != r2->flow_label)
1173 return false;
1174
1175 if (r1->fragment != r2->fragment)
1176 return false;
1177
1178 if (r1->protocol != r2->protocol)
1179 return false;
1180 return true;
1181 }
1182
1183 uint32_t bgp_pbr_rule_hash_key(const void *arg)
1184 {
1185 const struct bgp_pbr_rule *pbr = arg;
1186 uint32_t key;
1187
1188 key = prefix_hash_key(&pbr->src);
1189 key = jhash_1word(pbr->vrf_id, key);
1190 key = jhash_1word(pbr->flags, key);
1191 return jhash_1word(prefix_hash_key(&pbr->dst), key);
1192 }
1193
1194 bool bgp_pbr_rule_hash_equal(const void *arg1, const void *arg2)
1195 {
1196 const struct bgp_pbr_rule *r1, *r2;
1197
1198 r1 = (const struct bgp_pbr_rule *)arg1;
1199 r2 = (const struct bgp_pbr_rule *)arg2;
1200
1201 if (r1->vrf_id != r2->vrf_id)
1202 return false;
1203
1204 if (r1->flags != r2->flags)
1205 return false;
1206
1207 if (r1->action != r2->action)
1208 return false;
1209
1210 if ((r1->flags & MATCH_IP_SRC_SET) &&
1211 !prefix_same(&r1->src, &r2->src))
1212 return false;
1213
1214 if ((r1->flags & MATCH_IP_DST_SET) &&
1215 !prefix_same(&r1->dst, &r2->dst))
1216 return false;
1217
1218 return true;
1219 }
1220
1221 uint32_t bgp_pbr_match_entry_hash_key(const void *arg)
1222 {
1223 const struct bgp_pbr_match_entry *pbme;
1224 uint32_t key;
1225
1226 pbme = arg;
1227 key = prefix_hash_key(&pbme->src);
1228 key = jhash_1word(prefix_hash_key(&pbme->dst), key);
1229 key = jhash(&pbme->dst_port_min, 2, key);
1230 key = jhash(&pbme->src_port_min, 2, key);
1231 key = jhash(&pbme->dst_port_max, 2, key);
1232 key = jhash(&pbme->src_port_max, 2, key);
1233 key = jhash(&pbme->proto, 1, key);
1234
1235 return key;
1236 }
1237
1238 bool bgp_pbr_match_entry_hash_equal(const void *arg1, const void *arg2)
1239 {
1240 const struct bgp_pbr_match_entry *r1, *r2;
1241
1242 r1 = (const struct bgp_pbr_match_entry *)arg1;
1243 r2 = (const struct bgp_pbr_match_entry *)arg2;
1244
1245 /*
1246 * on updates, comparing backpointer is not necessary
1247 * unique value is self calculated
1248 * rate is ignored for now
1249 */
1250
1251 if (!prefix_same(&r1->src, &r2->src))
1252 return false;
1253
1254 if (!prefix_same(&r1->dst, &r2->dst))
1255 return false;
1256
1257 if (r1->src_port_min != r2->src_port_min)
1258 return false;
1259
1260 if (r1->dst_port_min != r2->dst_port_min)
1261 return false;
1262
1263 if (r1->src_port_max != r2->src_port_max)
1264 return false;
1265
1266 if (r1->dst_port_max != r2->dst_port_max)
1267 return false;
1268
1269 if (r1->proto != r2->proto)
1270 return false;
1271
1272 return true;
1273 }
1274
1275 uint32_t bgp_pbr_action_hash_key(const void *arg)
1276 {
1277 const struct bgp_pbr_action *pbra;
1278 uint32_t key;
1279
1280 pbra = arg;
1281 key = jhash_1word(pbra->table_id, 0x4312abde);
1282 key = jhash_1word(pbra->fwmark, key);
1283 key = jhash_1word(pbra->afi, key);
1284 return key;
1285 }
1286
1287 bool bgp_pbr_action_hash_equal(const void *arg1, const void *arg2)
1288 {
1289 const struct bgp_pbr_action *r1, *r2;
1290
1291 r1 = (const struct bgp_pbr_action *)arg1;
1292 r2 = (const struct bgp_pbr_action *)arg2;
1293
1294 /* unique value is self calculated
1295 * table and fwmark is self calculated
1296 * rate is ignored
1297 */
1298 if (r1->vrf_id != r2->vrf_id)
1299 return false;
1300
1301 if (r1->afi != r2->afi)
1302 return false;
1303
1304 return nexthop_same(&r1->nh, &r2->nh);
1305 }
1306
1307 struct bgp_pbr_rule *bgp_pbr_rule_lookup(vrf_id_t vrf_id,
1308 uint32_t unique)
1309 {
1310 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1311 struct bgp_pbr_rule_unique bpru;
1312
1313 if (!bgp || unique == 0)
1314 return NULL;
1315 bpru.unique = unique;
1316 bpru.bpr_found = NULL;
1317 hash_walk(bgp->pbr_rule_hash, bgp_pbr_rule_walkcb, &bpru);
1318 return bpru.bpr_found;
1319 }
1320
1321 struct bgp_pbr_action *bgp_pbr_action_rule_lookup(vrf_id_t vrf_id,
1322 uint32_t unique)
1323 {
1324 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1325 struct bgp_pbr_action_unique bpau;
1326
1327 if (!bgp || unique == 0)
1328 return NULL;
1329 bpau.unique = unique;
1330 bpau.bpa_found = NULL;
1331 hash_walk(bgp->pbr_action_hash, bgp_pbr_action_walkcb, &bpau);
1332 return bpau.bpa_found;
1333 }
1334
1335 struct bgp_pbr_match *bgp_pbr_match_ipset_lookup(vrf_id_t vrf_id,
1336 uint32_t unique)
1337 {
1338 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1339 struct bgp_pbr_match_unique bpmu;
1340
1341 if (!bgp || unique == 0)
1342 return NULL;
1343 bpmu.unique = unique;
1344 bpmu.bpm_found = NULL;
1345 hash_walk(bgp->pbr_match_hash, bgp_pbr_match_walkcb, &bpmu);
1346 return bpmu.bpm_found;
1347 }
1348
1349 struct bgp_pbr_match_entry *bgp_pbr_match_ipset_entry_lookup(vrf_id_t vrf_id,
1350 char *ipset_name,
1351 uint32_t unique)
1352 {
1353 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1354 struct bgp_pbr_match_entry_unique bpmeu;
1355 struct bgp_pbr_match_ipsetname bpmi;
1356
1357 if (!bgp || unique == 0)
1358 return NULL;
1359 bpmi.ipsetname = XCALLOC(MTYPE_TMP, ZEBRA_IPSET_NAME_SIZE);
1360 snprintf(bpmi.ipsetname, ZEBRA_IPSET_NAME_SIZE, "%s", ipset_name);
1361 bpmi.bpm_found = NULL;
1362 hash_walk(bgp->pbr_match_hash, bgp_pbr_match_pername_walkcb, &bpmi);
1363 XFREE(MTYPE_TMP, bpmi.ipsetname);
1364 if (!bpmi.bpm_found)
1365 return NULL;
1366 bpmeu.bpme_found = NULL;
1367 bpmeu.unique = unique;
1368 hash_walk(bpmi.bpm_found->entry_hash,
1369 bgp_pbr_match_entry_walkcb, &bpmeu);
1370 return bpmeu.bpme_found;
1371 }
1372
1373 struct bgp_pbr_match *bgp_pbr_match_iptable_lookup(vrf_id_t vrf_id,
1374 uint32_t unique)
1375 {
1376 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1377 struct bgp_pbr_match_iptable_unique bpmiu;
1378
1379 if (!bgp || unique == 0)
1380 return NULL;
1381 bpmiu.unique = unique;
1382 bpmiu.bpm_found = NULL;
1383 hash_walk(bgp->pbr_match_hash, bgp_pbr_match_iptable_walkcb, &bpmiu);
1384 return bpmiu.bpm_found;
1385 }
1386
1387 void bgp_pbr_cleanup(struct bgp *bgp)
1388 {
1389 if (bgp->pbr_match_hash) {
1390 hash_clean(bgp->pbr_match_hash, bgp_pbr_match_free);
1391 hash_free(bgp->pbr_match_hash);
1392 bgp->pbr_match_hash = NULL;
1393 }
1394 if (bgp->pbr_rule_hash) {
1395 hash_clean(bgp->pbr_rule_hash, bgp_pbr_rule_free);
1396 hash_free(bgp->pbr_rule_hash);
1397 bgp->pbr_rule_hash = NULL;
1398 }
1399 if (bgp->pbr_action_hash) {
1400 hash_clean(bgp->pbr_action_hash, bgp_pbr_action_free);
1401 hash_free(bgp->pbr_action_hash);
1402 bgp->pbr_action_hash = NULL;
1403 }
1404 if (bgp->bgp_pbr_cfg == NULL)
1405 return;
1406 bgp_pbr_reset(bgp, AFI_IP);
1407 bgp_pbr_reset(bgp, AFI_IP6);
1408 XFREE(MTYPE_PBR, bgp->bgp_pbr_cfg);
1409 }
1410
1411 void bgp_pbr_init(struct bgp *bgp)
1412 {
1413 bgp->pbr_match_hash =
1414 hash_create_size(8, bgp_pbr_match_hash_key,
1415 bgp_pbr_match_hash_equal,
1416 "Match Hash");
1417 bgp->pbr_action_hash =
1418 hash_create_size(8, bgp_pbr_action_hash_key,
1419 bgp_pbr_action_hash_equal,
1420 "Match Hash Entry");
1421
1422 bgp->pbr_rule_hash =
1423 hash_create_size(8, bgp_pbr_rule_hash_key,
1424 bgp_pbr_rule_hash_equal,
1425 "Match Rule");
1426
1427 bgp->bgp_pbr_cfg = XCALLOC(MTYPE_PBR, sizeof(struct bgp_pbr_config));
1428 bgp->bgp_pbr_cfg->pbr_interface_any_ipv4 = true;
1429 }
1430
1431 void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api)
1432 {
1433 int i = 0;
1434 char return_string[512];
1435 char *ptr = return_string;
1436 int nb_items = 0;
1437 int delta, len = sizeof(return_string);
1438
1439 delta = snprintf(ptr, sizeof(return_string), "MATCH : ");
1440 len -= delta;
1441 ptr += delta;
1442 if (api->match_bitmask & PREFIX_SRC_PRESENT) {
1443 struct prefix *p = &(api->src_prefix);
1444
1445 if (api->src_prefix_offset)
1446 delta = snprintfrr(ptr, len, "@src %pFX/off%u", p,
1447 api->src_prefix_offset);
1448 else
1449 delta = snprintfrr(ptr, len, "@src %pFX", p);
1450 len -= delta;
1451 ptr += delta;
1452 INCREMENT_DISPLAY(ptr, nb_items, len);
1453 }
1454 if (api->match_bitmask & PREFIX_DST_PRESENT) {
1455 struct prefix *p = &(api->dst_prefix);
1456
1457 INCREMENT_DISPLAY(ptr, nb_items, len);
1458 if (api->dst_prefix_offset)
1459 delta = snprintfrr(ptr, len, "@dst %pFX/off%u", p,
1460 api->dst_prefix_offset);
1461 else
1462 delta = snprintfrr(ptr, len, "@dst %pFX", p);
1463 len -= delta;
1464 ptr += delta;
1465 }
1466
1467 if (api->match_protocol_num)
1468 INCREMENT_DISPLAY(ptr, nb_items, len);
1469 for (i = 0; i < api->match_protocol_num; i++) {
1470 delta = snprintf_bgp_pbr_match_val(ptr, len, &api->protocol[i],
1471 i > 0 ? NULL : "@proto ");
1472 len -= delta;
1473 ptr += delta;
1474 }
1475
1476 if (api->match_src_port_num)
1477 INCREMENT_DISPLAY(ptr, nb_items, len);
1478 for (i = 0; i < api->match_src_port_num; i++) {
1479 delta = snprintf_bgp_pbr_match_val(ptr, len, &api->src_port[i],
1480 i > 0 ? NULL : "@srcport ");
1481 len -= delta;
1482 ptr += delta;
1483 }
1484
1485 if (api->match_dst_port_num)
1486 INCREMENT_DISPLAY(ptr, nb_items, len);
1487 for (i = 0; i < api->match_dst_port_num; i++) {
1488 delta = snprintf_bgp_pbr_match_val(ptr, len, &api->dst_port[i],
1489 i > 0 ? NULL : "@dstport ");
1490 len -= delta;
1491 ptr += delta;
1492 }
1493
1494 if (api->match_port_num)
1495 INCREMENT_DISPLAY(ptr, nb_items, len);
1496 for (i = 0; i < api->match_port_num; i++) {
1497 delta = snprintf_bgp_pbr_match_val(ptr, len, &api->port[i],
1498 i > 0 ? NULL : "@port ");
1499 len -= delta;
1500 ptr += delta;
1501 }
1502
1503 if (api->match_icmp_type_num)
1504 INCREMENT_DISPLAY(ptr, nb_items, len);
1505 for (i = 0; i < api->match_icmp_type_num; i++) {
1506 delta = snprintf_bgp_pbr_match_val(ptr, len, &api->icmp_type[i],
1507 i > 0 ? NULL : "@icmptype ");
1508 len -= delta;
1509 ptr += delta;
1510 }
1511
1512 if (api->match_icmp_code_num)
1513 INCREMENT_DISPLAY(ptr, nb_items, len);
1514 for (i = 0; i < api->match_icmp_code_num; i++) {
1515 delta = snprintf_bgp_pbr_match_val(ptr, len, &api->icmp_code[i],
1516 i > 0 ? NULL : "@icmpcode ");
1517 len -= delta;
1518 ptr += delta;
1519 }
1520
1521 if (api->match_packet_length_num)
1522 INCREMENT_DISPLAY(ptr, nb_items, len);
1523 for (i = 0; i < api->match_packet_length_num; i++) {
1524 delta = snprintf_bgp_pbr_match_val(ptr, len,
1525 &api->packet_length[i],
1526 i > 0 ? NULL : "@plen ");
1527 len -= delta;
1528 ptr += delta;
1529 }
1530
1531 if (api->match_dscp_num)
1532 INCREMENT_DISPLAY(ptr, nb_items, len);
1533 for (i = 0; i < api->match_dscp_num; i++) {
1534 delta = snprintf_bgp_pbr_match_val(ptr, len, &api->dscp[i],
1535 i > 0 ? NULL : "@dscp ");
1536 len -= delta;
1537 ptr += delta;
1538 }
1539
1540 if (api->match_flowlabel_num)
1541 INCREMENT_DISPLAY(ptr, nb_items, len);
1542 for (i = 0; i < api->match_flowlabel_num; i++) {
1543 delta = snprintf_bgp_pbr_match_val(ptr, len,
1544 &api->flow_label[i],
1545 i > 0 ? NULL : "@flowlabel ");
1546 len -= delta;
1547 ptr += delta;
1548 }
1549
1550 if (api->match_tcpflags_num)
1551 INCREMENT_DISPLAY(ptr, nb_items, len);
1552 for (i = 0; i < api->match_tcpflags_num; i++) {
1553 delta = snprintf_bgp_pbr_match_val(ptr, len, &api->tcpflags[i],
1554 i > 0 ? NULL : "@tcpflags ");
1555 len -= delta;
1556 ptr += delta;
1557 }
1558
1559 if (api->match_fragment_num)
1560 INCREMENT_DISPLAY(ptr, nb_items, len);
1561 for (i = 0; i < api->match_fragment_num; i++) {
1562 delta = snprintf_bgp_pbr_match_val(ptr, len, &api->fragment[i],
1563 i > 0 ? NULL : "@fragment ");
1564 len -= delta;
1565 ptr += delta;
1566 }
1567
1568 len = sizeof(return_string);
1569 if (!nb_items) {
1570 ptr = return_string;
1571 } else {
1572 len -= (ptr - return_string);
1573 delta = snprintf(ptr, len, "; ");
1574 len -= delta;
1575 ptr += delta;
1576 }
1577 if (api->action_num) {
1578 delta = snprintf(ptr, len, "SET : ");
1579 len -= delta;
1580 ptr += delta;
1581 }
1582 nb_items = 0;
1583 for (i = 0; i < api->action_num; i++) {
1584 switch (api->actions[i].action) {
1585 case ACTION_TRAFFICRATE:
1586 INCREMENT_DISPLAY(ptr, nb_items, len);
1587 delta = snprintf(ptr, len, "@set rate %f",
1588 api->actions[i].u.r.rate);
1589 len -= delta;
1590 ptr += delta;
1591 break;
1592 case ACTION_TRAFFIC_ACTION:
1593 INCREMENT_DISPLAY(ptr, nb_items, len);
1594 delta = snprintf(ptr, len, "@action ");
1595 len -= delta;
1596 ptr += delta;
1597 if (api->actions[i].u.za.filter
1598 & TRAFFIC_ACTION_TERMINATE) {
1599 delta = snprintf(ptr, len,
1600 " terminate (apply filter(s))");
1601 len -= delta;
1602 ptr += delta;
1603 }
1604 if (api->actions[i].u.za.filter
1605 & TRAFFIC_ACTION_DISTRIBUTE) {
1606 delta = snprintf(ptr, len, " distribute");
1607 len -= delta;
1608 ptr += delta;
1609 }
1610 if (api->actions[i].u.za.filter
1611 & TRAFFIC_ACTION_SAMPLE) {
1612 delta = snprintf(ptr, len, " sample");
1613 len -= delta;
1614 ptr += delta;
1615 }
1616 break;
1617 case ACTION_REDIRECT_IP: {
1618 char local_buff[INET6_ADDRSTRLEN];
1619 void *ptr_ip;
1620
1621 INCREMENT_DISPLAY(ptr, nb_items, len);
1622 if (api->afi == AF_INET)
1623 ptr_ip = &api->actions[i].u.zr.redirect_ip_v4;
1624 else
1625 ptr_ip = &api->actions[i].u.zr.redirect_ip_v6;
1626 if (inet_ntop(afi2family(api->afi), ptr_ip, local_buff,
1627 sizeof(local_buff)) != NULL) {
1628 delta = snprintf(ptr, len,
1629 "@redirect ip nh %s", local_buff);
1630 len -= delta;
1631 ptr += delta;
1632 }
1633 break;
1634 }
1635 case ACTION_REDIRECT: {
1636 struct vrf *vrf;
1637
1638 vrf = vrf_lookup_by_id(api->actions[i].u.redirect_vrf);
1639 INCREMENT_DISPLAY(ptr, nb_items, len);
1640 delta = snprintf(ptr, len, "@redirect vrf %s(%u)",
1641 VRF_LOGNAME(vrf),
1642 api->actions[i].u.redirect_vrf);
1643 len -= delta;
1644 ptr += delta;
1645 break;
1646 }
1647 case ACTION_MARKING:
1648 INCREMENT_DISPLAY(ptr, nb_items, len);
1649 delta = snprintf(ptr, len, "@set dscp/flowlabel %u",
1650 api->actions[i].u.marking_dscp);
1651 len -= delta;
1652 ptr += delta;
1653 break;
1654 default:
1655 break;
1656 }
1657 }
1658 zlog_info("%s", return_string);
1659 }
1660
1661 static void bgp_pbr_flush_iprule(struct bgp *bgp, struct bgp_pbr_action *bpa,
1662 struct bgp_pbr_rule *bpr)
1663 {
1664 /* if bpr is null, do nothing
1665 */
1666 if (bpr == NULL)
1667 return;
1668 if (bpr->installed) {
1669 bgp_send_pbr_rule_action(bpa, bpr, false);
1670 bpr->installed = false;
1671 bpr->action->refcnt--;
1672 bpr->action = NULL;
1673 if (bpr->path) {
1674 struct bgp_path_info *path;
1675 struct bgp_path_info_extra *extra;
1676
1677 /* unlink path to bpme */
1678 path = (struct bgp_path_info *)bpr->path;
1679 extra = bgp_path_info_extra_get(path);
1680 if (extra->bgp_fs_iprule)
1681 listnode_delete(extra->bgp_fs_iprule, bpr);
1682 bpr->path = NULL;
1683 }
1684 }
1685 hash_release(bgp->pbr_rule_hash, bpr);
1686 bgp_pbr_bpa_remove(bpa);
1687 }
1688
1689 static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa,
1690 struct bgp_pbr_match *bpm,
1691 struct bgp_pbr_match_entry *bpme)
1692 {
1693 /* if bpme is null, bpm is also null
1694 */
1695 if (bpme == NULL)
1696 return;
1697 /* ipset del entry */
1698 if (bpme->installed) {
1699 bgp_send_pbr_ipset_entry_match(bpme, false);
1700 bpme->installed = false;
1701 bpme->backpointer = NULL;
1702 if (bpme->path) {
1703 struct bgp_path_info *path;
1704 struct bgp_path_info_extra *extra;
1705
1706 /* unlink path to bpme */
1707 path = (struct bgp_path_info *)bpme->path;
1708 extra = bgp_path_info_extra_get(path);
1709 if (extra->bgp_fs_pbr)
1710 listnode_delete(extra->bgp_fs_pbr, bpme);
1711 bpme->path = NULL;
1712 }
1713 }
1714 hash_release(bpm->entry_hash, bpme);
1715 if (hashcount(bpm->entry_hash) == 0) {
1716 /* delete iptable entry first */
1717 /* then delete ipset match */
1718 if (bpm->installed) {
1719 if (bpm->installed_in_iptable) {
1720 bgp_send_pbr_iptable(bpm->action,
1721 bpm, false);
1722 bpm->installed_in_iptable = false;
1723 bpm->action->refcnt--;
1724 }
1725 bgp_send_pbr_ipset_match(bpm, false);
1726 bpm->installed = false;
1727 bpm->action = NULL;
1728 }
1729 hash_release(bgp->pbr_match_hash, bpm);
1730 /* XXX release pbr_match_action if not used
1731 * note that drop does not need to call send_pbr_action
1732 */
1733 }
1734 bgp_pbr_bpa_remove(bpa);
1735 }
1736
1737 struct bgp_pbr_match_entry_remain {
1738 struct bgp_pbr_match_entry *bpme_to_match;
1739 struct bgp_pbr_match_entry *bpme_found;
1740 };
1741
1742 struct bgp_pbr_rule_remain {
1743 struct bgp_pbr_rule *bpr_to_match;
1744 struct bgp_pbr_rule *bpr_found;
1745 };
1746
1747 static int bgp_pbr_get_same_rule(struct hash_bucket *bucket, void *arg)
1748 {
1749 struct bgp_pbr_rule *r1 = (struct bgp_pbr_rule *)bucket->data;
1750 struct bgp_pbr_rule_remain *ctxt =
1751 (struct bgp_pbr_rule_remain *)arg;
1752 struct bgp_pbr_rule *r2;
1753
1754 r2 = ctxt->bpr_to_match;
1755
1756 if (r1->vrf_id != r2->vrf_id)
1757 return HASHWALK_CONTINUE;
1758
1759 if (r1->flags != r2->flags)
1760 return HASHWALK_CONTINUE;
1761
1762 if ((r1->flags & MATCH_IP_SRC_SET) &&
1763 !prefix_same(&r1->src, &r2->src))
1764 return HASHWALK_CONTINUE;
1765
1766 if ((r1->flags & MATCH_IP_DST_SET) &&
1767 !prefix_same(&r1->dst, &r2->dst))
1768 return HASHWALK_CONTINUE;
1769
1770 /* this function is used for two cases:
1771 * - remove an entry upon withdraw request
1772 * (case r2->action is null)
1773 * - replace an old iprule with different action
1774 * (case r2->action is != null)
1775 * the old one is removed after the new one
1776 * this is to avoid disruption in traffic
1777 */
1778 if (r2->action == NULL ||
1779 r1->action != r2->action) {
1780 ctxt->bpr_found = r1;
1781 return HASHWALK_ABORT;
1782 }
1783 return HASHWALK_CONTINUE;
1784 }
1785
1786 static int bgp_pbr_get_remaining_entry(struct hash_bucket *bucket, void *arg)
1787 {
1788 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)bucket->data;
1789 struct bgp_pbr_match_entry_remain *bpmer =
1790 (struct bgp_pbr_match_entry_remain *)arg;
1791 struct bgp_pbr_match *bpm_temp;
1792 struct bgp_pbr_match_entry *bpme = bpmer->bpme_to_match;
1793
1794 if (!bpme->backpointer ||
1795 bpm == bpme->backpointer ||
1796 bpme->backpointer->action == bpm->action)
1797 return HASHWALK_CONTINUE;
1798 /* ensure bpm other characteristics are equal */
1799 bpm_temp = bpme->backpointer;
1800 if (bpm_temp->vrf_id != bpm->vrf_id ||
1801 bpm_temp->type != bpm->type ||
1802 bpm_temp->flags != bpm->flags ||
1803 bpm_temp->tcp_flags != bpm->tcp_flags ||
1804 bpm_temp->tcp_mask_flags != bpm->tcp_mask_flags ||
1805 bpm_temp->pkt_len_min != bpm->pkt_len_min ||
1806 bpm_temp->pkt_len_max != bpm->pkt_len_max ||
1807 bpm_temp->dscp_value != bpm->dscp_value ||
1808 bpm_temp->flow_label != bpm->flow_label ||
1809 bpm_temp->family != bpm->family ||
1810 bpm_temp->fragment != bpm->fragment)
1811 return HASHWALK_CONTINUE;
1812
1813 /* look for remaining bpme */
1814 bpmer->bpme_found = hash_lookup(bpm->entry_hash, bpme);
1815 if (!bpmer->bpme_found)
1816 return HASHWALK_CONTINUE;
1817 return HASHWALK_ABORT;
1818 }
1819
1820 static void bgp_pbr_policyroute_remove_from_zebra_unit(
1821 struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf)
1822 {
1823 struct bgp_pbr_match temp;
1824 struct bgp_pbr_match_entry temp2;
1825 struct bgp_pbr_rule pbr_rule;
1826 struct bgp_pbr_rule *bpr;
1827 struct bgp_pbr_match *bpm;
1828 struct bgp_pbr_match_entry *bpme;
1829 struct bgp_pbr_match_entry_remain bpmer;
1830 struct bgp_pbr_range_port *src_port;
1831 struct bgp_pbr_range_port *dst_port;
1832 struct bgp_pbr_range_port *pkt_len;
1833 struct bgp_pbr_rule_remain bprr;
1834
1835 if (!bpf)
1836 return;
1837 src_port = bpf->src_port;
1838 dst_port = bpf->dst_port;
1839 pkt_len = bpf->pkt_len;
1840
1841 if (BGP_DEBUG(zebra, ZEBRA))
1842 bgp_pbr_dump_entry(bpf, false);
1843
1844 /* as we don't know information from EC
1845 * look for bpm that have the bpm
1846 * with vrf_id characteristics
1847 */
1848 memset(&temp2, 0, sizeof(temp2));
1849 memset(&temp, 0, sizeof(temp));
1850
1851 if (bpf->type == BGP_PBR_IPRULE) {
1852 memset(&pbr_rule, 0, sizeof(pbr_rule));
1853 pbr_rule.vrf_id = bpf->vrf_id;
1854 if (bpf->src) {
1855 prefix_copy(&pbr_rule.src, bpf->src);
1856 pbr_rule.flags |= MATCH_IP_SRC_SET;
1857 }
1858 if (bpf->dst) {
1859 prefix_copy(&pbr_rule.dst, bpf->dst);
1860 pbr_rule.flags |= MATCH_IP_DST_SET;
1861 }
1862 bpr = &pbr_rule;
1863 /* A previous entry may already exist
1864 * flush previous entry if necessary
1865 */
1866 bprr.bpr_to_match = bpr;
1867 bprr.bpr_found = NULL;
1868 hash_walk(bgp->pbr_rule_hash, bgp_pbr_get_same_rule, &bprr);
1869 if (bprr.bpr_found) {
1870 static struct bgp_pbr_rule *local_bpr;
1871 static struct bgp_pbr_action *local_bpa;
1872
1873 local_bpr = bprr.bpr_found;
1874 local_bpa = local_bpr->action;
1875 bgp_pbr_flush_iprule(bgp, local_bpa,
1876 local_bpr);
1877 }
1878 return;
1879 }
1880
1881 temp.family = bpf->family;
1882 if (bpf->src) {
1883 temp.flags |= MATCH_IP_SRC_SET;
1884 prefix_copy(&temp2.src, bpf->src);
1885 } else
1886 temp2.src.family = bpf->family;
1887 if (bpf->dst) {
1888 temp.flags |= MATCH_IP_DST_SET;
1889 prefix_copy(&temp2.dst, bpf->dst);
1890 } else
1891 temp2.dst.family = bpf->family;
1892 if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
1893 if (bpf->protocol == IPPROTO_ICMP)
1894 temp.flags |= MATCH_ICMP_SET;
1895 temp.flags |= MATCH_PORT_SRC_SET;
1896 temp2.src_port_min = src_port->min_port;
1897 if (src_port->max_port) {
1898 temp.flags |= MATCH_PORT_SRC_RANGE_SET;
1899 temp2.src_port_max = src_port->max_port;
1900 }
1901 }
1902 if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
1903 if (bpf->protocol == IPPROTO_ICMP)
1904 temp.flags |= MATCH_ICMP_SET;
1905 temp.flags |= MATCH_PORT_DST_SET;
1906 temp2.dst_port_min = dst_port->min_port;
1907 if (dst_port->max_port) {
1908 temp.flags |= MATCH_PORT_DST_RANGE_SET;
1909 temp2.dst_port_max = dst_port->max_port;
1910 }
1911 }
1912 temp2.proto = bpf->protocol;
1913
1914 if (pkt_len) {
1915 temp.pkt_len_min = pkt_len->min_port;
1916 if (pkt_len->max_port)
1917 temp.pkt_len_max = pkt_len->max_port;
1918 } else if (bpf->pkt_len_val) {
1919 if (bpf->pkt_len_val->mask)
1920 temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
1921 temp.pkt_len_min = bpf->pkt_len_val->val;
1922 }
1923 if (bpf->tcp_flags) {
1924 temp.tcp_flags = bpf->tcp_flags->val;
1925 temp.tcp_mask_flags = bpf->tcp_flags->mask;
1926 }
1927 if (bpf->dscp) {
1928 if (bpf->dscp->mask)
1929 temp.flags |= MATCH_DSCP_INVERSE_SET;
1930 else
1931 temp.flags |= MATCH_DSCP_SET;
1932 temp.dscp_value = bpf->dscp->val;
1933 }
1934 if (bpf->flow_label) {
1935 if (bpf->flow_label->mask)
1936 temp.flags |= MATCH_FLOW_LABEL_INVERSE_SET;
1937 else
1938 temp.flags |= MATCH_FLOW_LABEL_SET;
1939 temp.flow_label = bpf->flow_label->val;
1940 }
1941
1942 if (bpf->fragment) {
1943 if (bpf->fragment->mask)
1944 temp.flags |= MATCH_FRAGMENT_INVERSE_SET;
1945 temp.fragment = bpf->fragment->val;
1946 }
1947
1948 if (bpf->src == NULL || bpf->dst == NULL) {
1949 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
1950 temp.type = IPSET_NET_PORT;
1951 else
1952 temp.type = IPSET_NET;
1953 } else {
1954 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
1955 temp.type = IPSET_NET_PORT_NET;
1956 else
1957 temp.type = IPSET_NET_NET;
1958 }
1959 if (bpf->vrf_id == VRF_UNKNOWN) /* XXX case BGP destroy */
1960 temp.vrf_id = VRF_DEFAULT;
1961 else
1962 temp.vrf_id = bpf->vrf_id;
1963 bpme = &temp2;
1964 bpm = &temp;
1965 bpme->backpointer = bpm;
1966 /* right now, a previous entry may already exist
1967 * flush previous entry if necessary
1968 */
1969 bpmer.bpme_to_match = bpme;
1970 bpmer.bpme_found = NULL;
1971 hash_walk(bgp->pbr_match_hash, bgp_pbr_get_remaining_entry, &bpmer);
1972 if (bpmer.bpme_found) {
1973 static struct bgp_pbr_match *local_bpm;
1974 static struct bgp_pbr_action *local_bpa;
1975
1976 local_bpm = bpmer.bpme_found->backpointer;
1977 local_bpa = local_bpm->action;
1978 bgp_pbr_flush_entry(bgp, local_bpa,
1979 local_bpm, bpmer.bpme_found);
1980 }
1981 }
1982
1983 static uint8_t bgp_pbr_next_type_entry(uint8_t type_entry)
1984 {
1985 if (type_entry == FLOWSPEC_TCP_FLAGS)
1986 return FLOWSPEC_DSCP;
1987 if (type_entry == FLOWSPEC_DSCP)
1988 return FLOWSPEC_FLOW_LABEL;
1989 if (type_entry == FLOWSPEC_FLOW_LABEL)
1990 return FLOWSPEC_PKT_LEN;
1991 if (type_entry == FLOWSPEC_PKT_LEN)
1992 return FLOWSPEC_FRAGMENT;
1993 if (type_entry == FLOWSPEC_FRAGMENT)
1994 return FLOWSPEC_ICMP_TYPE;
1995 return 0;
1996 }
1997
1998 static void bgp_pbr_icmp_action(struct bgp *bgp, struct bgp_path_info *path,
1999 struct bgp_pbr_filter *bpf,
2000 struct bgp_pbr_or_filter *bpof, bool add,
2001 struct nexthop *nh, float *rate)
2002 {
2003 struct bgp_pbr_range_port srcp, dstp;
2004 struct bgp_pbr_val_mask *icmp_type, *icmp_code;
2005 struct listnode *tnode, *cnode;
2006
2007 if (!bpf)
2008 return;
2009 if (bpf->protocol != IPPROTO_ICMP)
2010 return;
2011
2012 memset(&srcp, 0, sizeof(srcp));
2013 memset(&dstp, 0, sizeof(dstp));
2014 bpf->src_port = &srcp;
2015 bpf->dst_port = &dstp;
2016 /* parse icmp type and lookup appropriate icmp code
2017 * if no icmp code found, create as many entryes as
2018 * there are listed icmp codes for that icmp type
2019 */
2020 if (!bpof->icmp_type) {
2021 srcp.min_port = 0;
2022 srcp.max_port = 255;
2023 for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) {
2024 dstp.min_port = icmp_code->val;
2025 if (add)
2026 bgp_pbr_policyroute_add_to_zebra_unit(
2027 bgp, path, bpf, nh, rate);
2028 else
2029 bgp_pbr_policyroute_remove_from_zebra_unit(
2030 bgp, path, bpf);
2031 }
2032 return;
2033 }
2034 for (ALL_LIST_ELEMENTS_RO(bpof->icmp_type, tnode, icmp_type)) {
2035 srcp.min_port = icmp_type->val;
2036 srcp.max_port = 0;
2037 dstp.max_port = 0;
2038 /* only icmp type. create an entry only with icmp type */
2039 if (!bpof->icmp_code) {
2040 /* icmp type is not one of the above
2041 * forge an entry only based on the icmp type
2042 */
2043 dstp.min_port = 0;
2044 dstp.max_port = 255;
2045 if (add)
2046 bgp_pbr_policyroute_add_to_zebra_unit(
2047 bgp, path, bpf, nh, rate);
2048 else
2049 bgp_pbr_policyroute_remove_from_zebra_unit(
2050 bgp, path, bpf);
2051 continue;
2052 }
2053 for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) {
2054 dstp.min_port = icmp_code->val;
2055 if (add)
2056 bgp_pbr_policyroute_add_to_zebra_unit(
2057 bgp, path, bpf, nh, rate);
2058 else
2059 bgp_pbr_policyroute_remove_from_zebra_unit(
2060 bgp, path, bpf);
2061 }
2062 }
2063
2064 bpf->src_port = NULL;
2065 bpf->dst_port = NULL;
2066 }
2067
2068 static void bgp_pbr_policyroute_remove_from_zebra_recursive(
2069 struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf,
2070 struct bgp_pbr_or_filter *bpof, uint8_t type_entry)
2071 {
2072 struct listnode *node, *nnode;
2073 struct bgp_pbr_val_mask *valmask;
2074 uint8_t next_type_entry;
2075 struct list *orig_list;
2076 struct bgp_pbr_val_mask **target_val;
2077
2078 if (type_entry == 0) {
2079 bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path, bpf);
2080 return;
2081 }
2082 next_type_entry = bgp_pbr_next_type_entry(type_entry);
2083 if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
2084 orig_list = bpof->tcpflags;
2085 target_val = &bpf->tcp_flags;
2086 } else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
2087 orig_list = bpof->dscp;
2088 target_val = &bpf->dscp;
2089 } else if (type_entry == FLOWSPEC_FLOW_LABEL && bpof->flowlabel) {
2090 orig_list = bpof->flowlabel;
2091 target_val = &bpf->flow_label;
2092 } else if (type_entry == FLOWSPEC_PKT_LEN && bpof->pkt_len) {
2093 orig_list = bpof->pkt_len;
2094 target_val = &bpf->pkt_len_val;
2095 } else if (type_entry == FLOWSPEC_FRAGMENT && bpof->fragment) {
2096 orig_list = bpof->fragment;
2097 target_val = &bpf->fragment;
2098 } else if (type_entry == FLOWSPEC_ICMP_TYPE &&
2099 (bpof->icmp_type || bpof->icmp_code)) {
2100 /* enumerate list for icmp - must be last one */
2101 bgp_pbr_icmp_action(bgp, path, bpf, bpof, false, NULL, NULL);
2102 return;
2103 } else {
2104 bgp_pbr_policyroute_remove_from_zebra_recursive(
2105 bgp, path, bpf, bpof, next_type_entry);
2106 return;
2107 }
2108 for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
2109 *target_val = valmask;
2110 bgp_pbr_policyroute_remove_from_zebra_recursive(
2111 bgp, path, bpf, bpof, next_type_entry);
2112 }
2113 }
2114
2115 static void bgp_pbr_policyroute_remove_from_zebra(
2116 struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf,
2117 struct bgp_pbr_or_filter *bpof)
2118 {
2119 if (!bpof) {
2120 bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path, bpf);
2121 return;
2122 }
2123 if (bpof->tcpflags)
2124 bgp_pbr_policyroute_remove_from_zebra_recursive(
2125 bgp, path, bpf, bpof, FLOWSPEC_TCP_FLAGS);
2126 else if (bpof->dscp)
2127 bgp_pbr_policyroute_remove_from_zebra_recursive(
2128 bgp, path, bpf, bpof, FLOWSPEC_DSCP);
2129 else if (bpof->flowlabel)
2130 bgp_pbr_policyroute_remove_from_zebra_recursive(
2131 bgp, path, bpf, bpof, FLOWSPEC_FLOW_LABEL);
2132 else if (bpof->pkt_len)
2133 bgp_pbr_policyroute_remove_from_zebra_recursive(
2134 bgp, path, bpf, bpof, FLOWSPEC_PKT_LEN);
2135 else if (bpof->fragment)
2136 bgp_pbr_policyroute_remove_from_zebra_recursive(
2137 bgp, path, bpf, bpof, FLOWSPEC_FRAGMENT);
2138 else if (bpof->icmp_type || bpof->icmp_code)
2139 bgp_pbr_policyroute_remove_from_zebra_recursive(
2140 bgp, path, bpf, bpof, FLOWSPEC_ICMP_TYPE);
2141 else
2142 bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path, bpf);
2143 /* flush bpof */
2144 if (bpof->tcpflags)
2145 list_delete_all_node(bpof->tcpflags);
2146 if (bpof->dscp)
2147 list_delete_all_node(bpof->dscp);
2148 if (bpof->flowlabel)
2149 list_delete_all_node(bpof->flowlabel);
2150 if (bpof->pkt_len)
2151 list_delete_all_node(bpof->pkt_len);
2152 if (bpof->fragment)
2153 list_delete_all_node(bpof->fragment);
2154 }
2155
2156 static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add)
2157 {
2158 struct bgp_pbr_range_port *src_port;
2159 struct bgp_pbr_range_port *dst_port;
2160 struct bgp_pbr_range_port *pkt_len;
2161 char bufsrc[64], bufdst[64];
2162 char buffer[64];
2163 int remaining_len = 0;
2164 char protocol_str[16];
2165
2166 if (!bpf)
2167 return;
2168 src_port = bpf->src_port;
2169 dst_port = bpf->dst_port;
2170 pkt_len = bpf->pkt_len;
2171
2172 protocol_str[0] = '\0';
2173 if (bpf->tcp_flags && bpf->tcp_flags->mask)
2174 bpf->protocol = IPPROTO_TCP;
2175 if (bpf->protocol)
2176 snprintf(protocol_str, sizeof(protocol_str),
2177 "proto %d", bpf->protocol);
2178 buffer[0] = '\0';
2179 if (bpf->protocol == IPPROTO_ICMP && src_port && dst_port)
2180 remaining_len += snprintf(buffer, sizeof(buffer),
2181 "type %d, code %d",
2182 src_port->min_port,
2183 dst_port->min_port);
2184 else if (bpf->protocol == IPPROTO_UDP ||
2185 bpf->protocol == IPPROTO_TCP) {
2186
2187 if (src_port && src_port->min_port)
2188 remaining_len += snprintf(buffer,
2189 sizeof(buffer),
2190 "from [%u:%u]",
2191 src_port->min_port,
2192 src_port->max_port ?
2193 src_port->max_port :
2194 src_port->min_port);
2195 if (dst_port && dst_port->min_port)
2196 remaining_len += snprintf(buffer +
2197 remaining_len,
2198 sizeof(buffer)
2199 - remaining_len,
2200 "to [%u:%u]",
2201 dst_port->min_port,
2202 dst_port->max_port ?
2203 dst_port->max_port :
2204 dst_port->min_port);
2205 }
2206 if (pkt_len && (pkt_len->min_port || pkt_len->max_port)) {
2207 remaining_len += snprintf(buffer + remaining_len,
2208 sizeof(buffer)
2209 - remaining_len,
2210 " len [%u:%u]",
2211 pkt_len->min_port,
2212 pkt_len->max_port ?
2213 pkt_len->max_port :
2214 pkt_len->min_port);
2215 } else if (bpf->pkt_len_val) {
2216 remaining_len += snprintf(buffer + remaining_len,
2217 sizeof(buffer)
2218 - remaining_len,
2219 " %s len %u",
2220 bpf->pkt_len_val->mask
2221 ? "!" : "",
2222 bpf->pkt_len_val->val);
2223 }
2224 if (bpf->tcp_flags) {
2225 remaining_len += snprintf(buffer + remaining_len,
2226 sizeof(buffer)
2227 - remaining_len,
2228 "tcpflags %x/%x",
2229 bpf->tcp_flags->val,
2230 bpf->tcp_flags->mask);
2231 }
2232 if (bpf->dscp) {
2233 snprintf(buffer + remaining_len,
2234 sizeof(buffer)
2235 - remaining_len,
2236 "%s dscp %d",
2237 bpf->dscp->mask
2238 ? "!" : "",
2239 bpf->dscp->val);
2240 }
2241 if (bpf->flow_label) {
2242 snprintf(buffer + remaining_len,
2243 sizeof(buffer)
2244 - remaining_len,
2245 "%s flow_label %d",
2246 bpf->flow_label->mask
2247 ? "!" : "",
2248 bpf->flow_label->val);
2249 }
2250 zlog_debug("BGP: %s FS PBR from %s to %s, %s %s",
2251 add ? "adding" : "removing",
2252 bpf->src == NULL ? "<all>" :
2253 prefix2str(bpf->src, bufsrc, sizeof(bufsrc)),
2254 bpf->dst == NULL ? "<all>" :
2255 prefix2str(bpf->dst, bufdst, sizeof(bufdst)),
2256 protocol_str, buffer);
2257
2258 }
2259
2260 static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
2261 struct bgp_path_info *path,
2262 struct bgp_pbr_filter *bpf,
2263 struct nexthop *nh,
2264 float *rate)
2265 {
2266 struct bgp_pbr_match temp;
2267 struct bgp_pbr_match_entry temp2;
2268 struct bgp_pbr_match *bpm;
2269 struct bgp_pbr_match_entry *bpme = NULL;
2270 struct bgp_pbr_action temp3;
2271 struct bgp_pbr_action *bpa = NULL;
2272 struct bgp_pbr_match_entry_remain bpmer;
2273 struct bgp_pbr_rule_remain bprr;
2274 struct bgp_pbr_range_port *src_port;
2275 struct bgp_pbr_range_port *dst_port;
2276 struct bgp_pbr_range_port *pkt_len;
2277 struct bgp_pbr_rule pbr_rule;
2278 struct bgp_pbr_rule *bpr;
2279 bool bpr_found = false;
2280 bool bpme_found = false;
2281 struct vrf *vrf = NULL;
2282
2283 if (!bpf)
2284 return;
2285 src_port = bpf->src_port;
2286 dst_port = bpf->dst_port;
2287 pkt_len = bpf->pkt_len;
2288
2289 if (BGP_DEBUG(zebra, ZEBRA))
2290 bgp_pbr_dump_entry(bpf, true);
2291
2292 /* look for bpa first */
2293 memset(&temp3, 0, sizeof(temp3));
2294 if (rate)
2295 temp3.rate = *rate;
2296 if (nh)
2297 memcpy(&temp3.nh, nh, sizeof(struct nexthop));
2298 temp3.vrf_id = bpf->vrf_id;
2299 temp3.afi = family2afi(bpf->family);
2300 bpa = hash_get(bgp->pbr_action_hash, &temp3,
2301 bgp_pbr_action_alloc_intern);
2302
2303 if (nh)
2304 vrf = vrf_lookup_by_id(nh->vrf_id);
2305 if (bpa->fwmark == 0) {
2306 /* drop is handled by iptable */
2307 if (nh && nh->type == NEXTHOP_TYPE_BLACKHOLE) {
2308 bpa->table_id = 0;
2309 bpa->installed = true;
2310 } else {
2311 bpa->fwmark = bgp_zebra_tm_get_id();
2312 /* if action is redirect-vrf, then
2313 * use directly table_id of vrf
2314 */
2315 if (nh && vrf && !vrf_is_backend_netns()
2316 && bpf->vrf_id != vrf->vrf_id)
2317 bpa->table_id = vrf->data.l.table_id;
2318 else
2319 bpa->table_id = bpa->fwmark;
2320 bpa->installed = false;
2321 }
2322 bpa->bgp = bgp;
2323 bpa->unique = ++bgp_pbr_action_counter_unique;
2324 /* 0 value is forbidden */
2325 bpa->install_in_progress = false;
2326 }
2327 if (bpf->type == BGP_PBR_IPRULE) {
2328 memset(&pbr_rule, 0, sizeof(pbr_rule));
2329 pbr_rule.vrf_id = bpf->vrf_id;
2330 pbr_rule.priority = 20;
2331 if (bpf->src) {
2332 pbr_rule.flags |= MATCH_IP_SRC_SET;
2333 prefix_copy(&pbr_rule.src, bpf->src);
2334 }
2335 if (bpf->dst) {
2336 pbr_rule.flags |= MATCH_IP_DST_SET;
2337 prefix_copy(&pbr_rule.dst, bpf->dst);
2338 }
2339 pbr_rule.action = bpa;
2340 bpr = hash_get(bgp->pbr_rule_hash, &pbr_rule,
2341 bgp_pbr_rule_alloc_intern);
2342 if (bpr->unique == 0) {
2343 bpr->unique = ++bgp_pbr_action_counter_unique;
2344 bpr->installed = false;
2345 bpr->install_in_progress = false;
2346 /* link bgp info to bpr */
2347 bpr->path = (void *)path;
2348 } else
2349 bpr_found = true;
2350 /* already installed */
2351 if (bpr_found) {
2352 struct bgp_path_info_extra *extra =
2353 bgp_path_info_extra_get(path);
2354
2355 if (extra &&
2356 listnode_lookup_nocheck(extra->bgp_fs_iprule,
2357 bpr)) {
2358 if (BGP_DEBUG(pbr, PBR_ERROR))
2359 zlog_err("%s: entry %p/%p already installed in bgp pbr iprule",
2360 __func__, path, bpr);
2361 return;
2362 }
2363 }
2364
2365 bgp_pbr_bpa_add(bpa);
2366
2367 /* ip rule add */
2368 if (!bpr->installed)
2369 bgp_send_pbr_rule_action(bpa, bpr, true);
2370
2371 /* A previous entry may already exist
2372 * flush previous entry if necessary
2373 */
2374 bprr.bpr_to_match = bpr;
2375 bprr.bpr_found = NULL;
2376 hash_walk(bgp->pbr_rule_hash, bgp_pbr_get_same_rule, &bprr);
2377 if (bprr.bpr_found) {
2378 static struct bgp_pbr_rule *local_bpr;
2379 static struct bgp_pbr_action *local_bpa;
2380
2381 local_bpr = bprr.bpr_found;
2382 local_bpa = local_bpr->action;
2383 bgp_pbr_flush_iprule(bgp, local_bpa,
2384 local_bpr);
2385 }
2386 return;
2387 }
2388 /* then look for bpm */
2389 memset(&temp, 0, sizeof(temp));
2390 temp.vrf_id = bpf->vrf_id;
2391 temp.family = bpf->family;
2392 if (bpf->src)
2393 temp.flags |= MATCH_IP_SRC_SET;
2394 if (bpf->dst)
2395 temp.flags |= MATCH_IP_DST_SET;
2396
2397 if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
2398 if (bpf->protocol == IPPROTO_ICMP)
2399 temp.flags |= MATCH_ICMP_SET;
2400 temp.flags |= MATCH_PORT_SRC_SET;
2401 }
2402 if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
2403 if (bpf->protocol == IPPROTO_ICMP)
2404 temp.flags |= MATCH_ICMP_SET;
2405 temp.flags |= MATCH_PORT_DST_SET;
2406 }
2407 if (src_port && src_port->max_port)
2408 temp.flags |= MATCH_PORT_SRC_RANGE_SET;
2409 if (dst_port && dst_port->max_port)
2410 temp.flags |= MATCH_PORT_DST_RANGE_SET;
2411
2412 if (bpf->src == NULL || bpf->dst == NULL) {
2413 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
2414 temp.type = IPSET_NET_PORT;
2415 else
2416 temp.type = IPSET_NET;
2417 } else {
2418 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
2419 temp.type = IPSET_NET_PORT_NET;
2420 else
2421 temp.type = IPSET_NET_NET;
2422 }
2423 if (pkt_len) {
2424 temp.pkt_len_min = pkt_len->min_port;
2425 if (pkt_len->max_port)
2426 temp.pkt_len_max = pkt_len->max_port;
2427 } else if (bpf->pkt_len_val) {
2428 if (bpf->pkt_len_val->mask)
2429 temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
2430 temp.pkt_len_min = bpf->pkt_len_val->val;
2431 }
2432 if (bpf->tcp_flags) {
2433 temp.tcp_flags = bpf->tcp_flags->val;
2434 temp.tcp_mask_flags = bpf->tcp_flags->mask;
2435 }
2436 if (bpf->dscp) {
2437 if (bpf->dscp->mask)
2438 temp.flags |= MATCH_DSCP_INVERSE_SET;
2439 else
2440 temp.flags |= MATCH_DSCP_SET;
2441 temp.dscp_value = bpf->dscp->val;
2442 }
2443 if (bpf->flow_label) {
2444 if (bpf->flow_label->mask)
2445 temp.flags |= MATCH_FLOW_LABEL_INVERSE_SET;
2446 else
2447 temp.flags |= MATCH_FLOW_LABEL_SET;
2448 temp.flow_label = bpf->flow_label->val;
2449 }
2450 if (bpf->fragment) {
2451 if (bpf->fragment->mask)
2452 temp.flags |= MATCH_FRAGMENT_INVERSE_SET;
2453 temp.fragment = bpf->fragment->val;
2454 }
2455 if (bpf->protocol) {
2456 temp.protocol = bpf->protocol;
2457 temp.flags |= MATCH_PROTOCOL_SET;
2458 }
2459 temp.action = bpa;
2460 bpm = hash_get(bgp->pbr_match_hash, &temp,
2461 bgp_pbr_match_alloc_intern);
2462
2463 /* new, then self allocate ipset_name and unique */
2464 if (bpm->unique == 0) {
2465 bpm->unique = ++bgp_pbr_match_counter_unique;
2466 /* 0 value is forbidden */
2467 snprintf(bpm->ipset_name, sizeof(bpm->ipset_name),
2468 "match%p", bpm);
2469 bpm->entry_hash = hash_create_size(8,
2470 bgp_pbr_match_entry_hash_key,
2471 bgp_pbr_match_entry_hash_equal,
2472 "Match Entry Hash");
2473 bpm->installed = false;
2474
2475 /* unique2 should be updated too */
2476 bpm->unique2 = ++bgp_pbr_match_iptable_counter_unique;
2477 bpm->installed_in_iptable = false;
2478 bpm->install_in_progress = false;
2479 bpm->install_iptable_in_progress = false;
2480 }
2481
2482 memset(&temp2, 0, sizeof(temp2));
2483 if (bpf->src)
2484 prefix_copy(&temp2.src, bpf->src);
2485 else
2486 temp2.src.family = bpf->family;
2487 if (bpf->dst)
2488 prefix_copy(&temp2.dst, bpf->dst);
2489 else
2490 temp2.dst.family = bpf->family;
2491 temp2.src_port_min = src_port ? src_port->min_port : 0;
2492 temp2.dst_port_min = dst_port ? dst_port->min_port : 0;
2493 temp2.src_port_max = src_port ? src_port->max_port : 0;
2494 temp2.dst_port_max = dst_port ? dst_port->max_port : 0;
2495 temp2.proto = bpf->protocol;
2496 bpme = hash_get(bpm->entry_hash, &temp2,
2497 bgp_pbr_match_entry_alloc_intern);
2498 if (bpme->unique == 0) {
2499 bpme->unique = ++bgp_pbr_match_entry_counter_unique;
2500 /* 0 value is forbidden */
2501 bpme->backpointer = bpm;
2502 bpme->installed = false;
2503 bpme->install_in_progress = false;
2504 /* link bgp info to bpme */
2505 bpme->path = (void *)path;
2506 } else
2507 bpme_found = true;
2508
2509 /* already installed */
2510 if (bpme_found) {
2511 struct bgp_path_info_extra *extra =
2512 bgp_path_info_extra_get(path);
2513
2514 if (extra &&
2515 listnode_lookup_nocheck(extra->bgp_fs_pbr, bpme)) {
2516 if (BGP_DEBUG(pbr, PBR_ERROR))
2517 zlog_err(
2518 "%s: entry %p/%p already installed in bgp pbr",
2519 __func__, path, bpme);
2520 return;
2521 }
2522 }
2523 /* BGP FS: append entry to zebra
2524 * - policies are not routing entries and as such
2525 * route replace semantics don't necessarily follow
2526 * through to policy entries
2527 * - because of that, not all policing information will be stored
2528 * into zebra. and non selected policies will be suppressed from zebra
2529 * - as consequence, in order to bring consistency
2530 * a policy will be added, then ifan ecmp policy exists,
2531 * it will be suppressed subsequently
2532 */
2533 /* ip rule add */
2534 bgp_pbr_bpa_add(bpa);
2535
2536 /* ipset create */
2537 if (!bpm->installed)
2538 bgp_send_pbr_ipset_match(bpm, true);
2539 /* ipset add */
2540 if (!bpme->installed)
2541 bgp_send_pbr_ipset_entry_match(bpme, true);
2542
2543 /* iptables */
2544 if (!bpm->installed_in_iptable)
2545 bgp_send_pbr_iptable(bpa, bpm, true);
2546
2547 /* A previous entry may already exist
2548 * flush previous entry if necessary
2549 */
2550 bpmer.bpme_to_match = bpme;
2551 bpmer.bpme_found = NULL;
2552 hash_walk(bgp->pbr_match_hash, bgp_pbr_get_remaining_entry, &bpmer);
2553 if (bpmer.bpme_found) {
2554 static struct bgp_pbr_match *local_bpm;
2555 static struct bgp_pbr_action *local_bpa;
2556
2557 local_bpm = bpmer.bpme_found->backpointer;
2558 local_bpa = local_bpm->action;
2559 bgp_pbr_flush_entry(bgp, local_bpa,
2560 local_bpm, bpmer.bpme_found);
2561 }
2562
2563
2564 }
2565
2566 static void bgp_pbr_policyroute_add_to_zebra_recursive(
2567 struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf,
2568 struct bgp_pbr_or_filter *bpof, struct nexthop *nh, float *rate,
2569 uint8_t type_entry)
2570 {
2571 struct listnode *node, *nnode;
2572 struct bgp_pbr_val_mask *valmask;
2573 uint8_t next_type_entry;
2574 struct list *orig_list;
2575 struct bgp_pbr_val_mask **target_val;
2576
2577 if (type_entry == 0) {
2578 bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh, rate);
2579 return;
2580 }
2581 next_type_entry = bgp_pbr_next_type_entry(type_entry);
2582 if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
2583 orig_list = bpof->tcpflags;
2584 target_val = &bpf->tcp_flags;
2585 } else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
2586 orig_list = bpof->dscp;
2587 target_val = &bpf->dscp;
2588 } else if (type_entry == FLOWSPEC_PKT_LEN && bpof->pkt_len) {
2589 orig_list = bpof->pkt_len;
2590 target_val = &bpf->pkt_len_val;
2591 } else if (type_entry == FLOWSPEC_FRAGMENT && bpof->fragment) {
2592 orig_list = bpof->fragment;
2593 target_val = &bpf->fragment;
2594 } else if (type_entry == FLOWSPEC_ICMP_TYPE &&
2595 (bpof->icmp_type || bpof->icmp_code)) {
2596 /* enumerate list for icmp - must be last one */
2597 bgp_pbr_icmp_action(bgp, path, bpf, bpof, true, nh, rate);
2598 return;
2599 } else {
2600 bgp_pbr_policyroute_add_to_zebra_recursive(
2601 bgp, path, bpf, bpof, nh, rate, next_type_entry);
2602 return;
2603 }
2604 for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
2605 *target_val = valmask;
2606 bgp_pbr_policyroute_add_to_zebra_recursive(
2607 bgp, path, bpf, bpof, nh, rate, next_type_entry);
2608 }
2609 }
2610
2611 static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
2612 struct bgp_path_info *path,
2613 struct bgp_pbr_filter *bpf,
2614 struct bgp_pbr_or_filter *bpof,
2615 struct nexthop *nh, float *rate)
2616 {
2617 if (!bpof) {
2618 bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh, rate);
2619 return;
2620 }
2621 if (bpof->tcpflags)
2622 bgp_pbr_policyroute_add_to_zebra_recursive(
2623 bgp, path, bpf, bpof, nh, rate, FLOWSPEC_TCP_FLAGS);
2624 else if (bpof->dscp)
2625 bgp_pbr_policyroute_add_to_zebra_recursive(
2626 bgp, path, bpf, bpof, nh, rate, FLOWSPEC_DSCP);
2627 else if (bpof->pkt_len)
2628 bgp_pbr_policyroute_add_to_zebra_recursive(
2629 bgp, path, bpf, bpof, nh, rate, FLOWSPEC_PKT_LEN);
2630 else if (bpof->fragment)
2631 bgp_pbr_policyroute_add_to_zebra_recursive(
2632 bgp, path, bpf, bpof, nh, rate, FLOWSPEC_FRAGMENT);
2633 else if (bpof->icmp_type || bpof->icmp_code)
2634 bgp_pbr_policyroute_add_to_zebra_recursive(
2635 bgp, path, bpf, bpof, nh, rate, FLOWSPEC_ICMP_TYPE);
2636 else
2637 bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh, rate);
2638 /* flush bpof */
2639 if (bpof->tcpflags)
2640 list_delete_all_node(bpof->tcpflags);
2641 if (bpof->dscp)
2642 list_delete_all_node(bpof->dscp);
2643 if (bpof->pkt_len)
2644 list_delete_all_node(bpof->pkt_len);
2645 if (bpof->fragment)
2646 list_delete_all_node(bpof->fragment);
2647 if (bpof->icmp_type)
2648 list_delete_all_node(bpof->icmp_type);
2649 if (bpof->icmp_code)
2650 list_delete_all_node(bpof->icmp_code);
2651 }
2652
2653 static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path,
2654 struct bgp_pbr_entry_main *api, bool add)
2655 {
2656 struct nexthop nh;
2657 int i = 0;
2658 int continue_loop = 1;
2659 float rate = 0;
2660 struct prefix *src = NULL, *dst = NULL;
2661 uint8_t proto = 0;
2662 struct bgp_pbr_range_port *srcp = NULL, *dstp = NULL;
2663 struct bgp_pbr_range_port range, range_icmp_code;
2664 struct bgp_pbr_range_port pkt_len;
2665 struct bgp_pbr_filter bpf;
2666 uint8_t kind_enum;
2667 struct bgp_pbr_or_filter bpof;
2668 struct bgp_pbr_val_mask bpvm;
2669
2670 memset(&range, 0, sizeof(range));
2671 memset(&nh, 0, sizeof(nh));
2672 memset(&bpf, 0, sizeof(bpf));
2673 memset(&bpof, 0, sizeof(bpof));
2674 if (api->match_bitmask & PREFIX_SRC_PRESENT ||
2675 (api->type == BGP_PBR_IPRULE &&
2676 api->match_bitmask_iprule & PREFIX_SRC_PRESENT))
2677 src = &api->src_prefix;
2678 if (api->match_bitmask & PREFIX_DST_PRESENT ||
2679 (api->type == BGP_PBR_IPRULE &&
2680 api->match_bitmask_iprule & PREFIX_DST_PRESENT))
2681 dst = &api->dst_prefix;
2682 if (api->type == BGP_PBR_IPRULE)
2683 bpf.type = api->type;
2684 memset(&nh, 0, sizeof(nh));
2685 nh.vrf_id = VRF_UNKNOWN;
2686 if (api->match_protocol_num) {
2687 proto = (uint8_t)api->protocol[0].value;
2688 if (api->afi == AF_INET6 && proto == IPPROTO_ICMPV6)
2689 proto = IPPROTO_ICMP;
2690 }
2691 /* if match_port is selected, then either src or dst port will be parsed
2692 * but not both at the same time
2693 */
2694 if (api->match_port_num >= 1) {
2695 bgp_pbr_extract(api->port,
2696 api->match_port_num,
2697 &range);
2698 srcp = dstp = &range;
2699 } else if (api->match_src_port_num >= 1) {
2700 bgp_pbr_extract(api->src_port,
2701 api->match_src_port_num,
2702 &range);
2703 srcp = &range;
2704 dstp = NULL;
2705 } else if (api->match_dst_port_num >= 1) {
2706 bgp_pbr_extract(api->dst_port,
2707 api->match_dst_port_num,
2708 &range);
2709 dstp = &range;
2710 srcp = NULL;
2711 }
2712 if (api->match_icmp_type_num >= 1) {
2713 proto = IPPROTO_ICMP;
2714 if (bgp_pbr_extract(api->icmp_type,
2715 api->match_icmp_type_num,
2716 &range))
2717 srcp = &range;
2718 else {
2719 bpof.icmp_type = list_new();
2720 bgp_pbr_extract_enumerate(api->icmp_type,
2721 api->match_icmp_type_num,
2722 OPERATOR_UNARY_OR,
2723 bpof.icmp_type,
2724 FLOWSPEC_ICMP_TYPE);
2725 }
2726 }
2727 if (api->match_icmp_code_num >= 1) {
2728 proto = IPPROTO_ICMP;
2729 if (bgp_pbr_extract(api->icmp_code,
2730 api->match_icmp_code_num,
2731 &range_icmp_code))
2732 dstp = &range_icmp_code;
2733 else {
2734 bpof.icmp_code = list_new();
2735 bgp_pbr_extract_enumerate(api->icmp_code,
2736 api->match_icmp_code_num,
2737 OPERATOR_UNARY_OR,
2738 bpof.icmp_code,
2739 FLOWSPEC_ICMP_CODE);
2740 }
2741 }
2742
2743 if (api->match_tcpflags_num) {
2744 kind_enum = bgp_pbr_match_val_get_operator(api->tcpflags,
2745 api->match_tcpflags_num);
2746 if (kind_enum == OPERATOR_UNARY_AND) {
2747 bpf.tcp_flags = &bpvm;
2748 bgp_pbr_extract_enumerate(api->tcpflags,
2749 api->match_tcpflags_num,
2750 OPERATOR_UNARY_AND,
2751 bpf.tcp_flags,
2752 FLOWSPEC_TCP_FLAGS);
2753 } else if (kind_enum == OPERATOR_UNARY_OR) {
2754 bpof.tcpflags = list_new();
2755 bgp_pbr_extract_enumerate(api->tcpflags,
2756 api->match_tcpflags_num,
2757 OPERATOR_UNARY_OR,
2758 bpof.tcpflags,
2759 FLOWSPEC_TCP_FLAGS);
2760 }
2761 }
2762 if (api->match_packet_length_num) {
2763 bool ret;
2764
2765 ret = bgp_pbr_extract(api->packet_length,
2766 api->match_packet_length_num,
2767 &pkt_len);
2768 if (ret)
2769 bpf.pkt_len = &pkt_len;
2770 else {
2771 bpof.pkt_len = list_new();
2772 bgp_pbr_extract_enumerate(api->packet_length,
2773 api->match_packet_length_num,
2774 OPERATOR_UNARY_OR,
2775 bpof.pkt_len,
2776 FLOWSPEC_PKT_LEN);
2777 }
2778 }
2779 if (api->match_dscp_num >= 1) {
2780 bpof.dscp = list_new();
2781 bgp_pbr_extract_enumerate(api->dscp, api->match_dscp_num,
2782 OPERATOR_UNARY_OR,
2783 bpof.dscp, FLOWSPEC_DSCP);
2784 }
2785 if (api->match_fragment_num) {
2786 bpof.fragment = list_new();
2787 bgp_pbr_extract_enumerate(api->fragment,
2788 api->match_fragment_num,
2789 OPERATOR_UNARY_OR,
2790 bpof.fragment,
2791 FLOWSPEC_FRAGMENT);
2792 }
2793 bpf.vrf_id = api->vrf_id;
2794 bpf.src = src;
2795 bpf.dst = dst;
2796 bpf.protocol = proto;
2797 bpf.src_port = srcp;
2798 bpf.dst_port = dstp;
2799 bpf.family = afi2family(api->afi);
2800 if (!add) {
2801 bgp_pbr_policyroute_remove_from_zebra(bgp, path, &bpf, &bpof);
2802 return;
2803 }
2804 /* no action for add = true */
2805 for (i = 0; i < api->action_num; i++) {
2806 switch (api->actions[i].action) {
2807 case ACTION_TRAFFICRATE:
2808 /* drop packet */
2809 if (api->actions[i].u.r.rate == 0) {
2810 nh.vrf_id = api->vrf_id;
2811 nh.type = NEXTHOP_TYPE_BLACKHOLE;
2812 bgp_pbr_policyroute_add_to_zebra(
2813 bgp, path, &bpf, &bpof, &nh, &rate);
2814 } else {
2815 /* update rate. can be reentrant */
2816 rate = api->actions[i].u.r.rate;
2817 if (BGP_DEBUG(pbr, PBR)) {
2818 bgp_pbr_print_policy_route(api);
2819 zlog_warn("PBR: ignoring Set action rate %f",
2820 api->actions[i].u.r.rate);
2821 }
2822 }
2823 break;
2824 case ACTION_TRAFFIC_ACTION:
2825 if (api->actions[i].u.za.filter
2826 & TRAFFIC_ACTION_SAMPLE) {
2827 if (BGP_DEBUG(pbr, PBR)) {
2828 bgp_pbr_print_policy_route(api);
2829 zlog_warn("PBR: Sample action Ignored");
2830 }
2831 }
2832 /* terminate action: run other filters
2833 */
2834 break;
2835 case ACTION_REDIRECT_IP:
2836 nh.vrf_id = api->vrf_id;
2837 if (api->afi == AFI_IP) {
2838 nh.type = NEXTHOP_TYPE_IPV4;
2839 nh.gate.ipv4.s_addr =
2840 api->actions[i].u.zr.
2841 redirect_ip_v4.s_addr;
2842 } else {
2843 nh.type = NEXTHOP_TYPE_IPV6;
2844 memcpy(&nh.gate.ipv6,
2845 &api->actions[i].u.zr.redirect_ip_v6,
2846 sizeof(struct in6_addr));
2847 }
2848 bgp_pbr_policyroute_add_to_zebra(bgp, path, &bpf, &bpof,
2849 &nh, &rate);
2850 /* XXX combination with REDIRECT_VRF
2851 * + REDIRECT_NH_IP not done
2852 */
2853 continue_loop = 0;
2854 break;
2855 case ACTION_REDIRECT:
2856 if (api->afi == AFI_IP)
2857 nh.type = NEXTHOP_TYPE_IPV4;
2858 else
2859 nh.type = NEXTHOP_TYPE_IPV6;
2860 nh.vrf_id = api->actions[i].u.redirect_vrf;
2861 bgp_pbr_policyroute_add_to_zebra(bgp, path, &bpf, &bpof,
2862 &nh, &rate);
2863 continue_loop = 0;
2864 break;
2865 case ACTION_MARKING:
2866 if (BGP_DEBUG(pbr, PBR)) {
2867 bgp_pbr_print_policy_route(api);
2868 zlog_warn("PBR: Set DSCP/FlowLabel %u Ignored",
2869 api->actions[i].u.marking_dscp);
2870 }
2871 break;
2872 default:
2873 break;
2874 }
2875 if (continue_loop == 0)
2876 break;
2877 }
2878 }
2879
2880 void bgp_pbr_update_entry(struct bgp *bgp, const struct prefix *p,
2881 struct bgp_path_info *info, afi_t afi, safi_t safi,
2882 bool nlri_update)
2883 {
2884 struct bgp_pbr_entry_main api;
2885
2886 if (safi != SAFI_FLOWSPEC)
2887 return; /* not supported */
2888 /* Make Zebra API structure. */
2889 memset(&api, 0, sizeof(api));
2890 api.vrf_id = bgp->vrf_id;
2891 api.afi = afi;
2892
2893 if (!bgp_zebra_tm_chunk_obtained()) {
2894 if (BGP_DEBUG(pbr, PBR_ERROR))
2895 flog_err(EC_BGP_TABLE_CHUNK,
2896 "%s: table chunk not obtained yet", __func__);
2897 return;
2898 }
2899
2900 if (bgp_pbr_build_and_validate_entry(p, info, &api) < 0) {
2901 if (BGP_DEBUG(pbr, PBR_ERROR))
2902 flog_err(EC_BGP_FLOWSPEC_INSTALLATION,
2903 "%s: cancel updating entry %p in bgp pbr",
2904 __func__, info);
2905 return;
2906 }
2907 bgp_pbr_handle_entry(bgp, info, &api, nlri_update);
2908 }
2909
2910 int bgp_pbr_interface_compare(const struct bgp_pbr_interface *a,
2911 const struct bgp_pbr_interface *b)
2912 {
2913 return strcmp(a->name, b->name);
2914 }
2915
2916 struct bgp_pbr_interface *bgp_pbr_interface_lookup(const char *name,
2917 struct bgp_pbr_interface_head *head)
2918 {
2919 struct bgp_pbr_interface pbr_if;
2920
2921 strlcpy(pbr_if.name, name, sizeof(pbr_if.name));
2922 return (RB_FIND(bgp_pbr_interface_head,
2923 head, &pbr_if));
2924 }
2925
2926 /* this function resets to the default policy routing
2927 * go back to default status
2928 */
2929 void bgp_pbr_reset(struct bgp *bgp, afi_t afi)
2930 {
2931 struct bgp_pbr_config *bgp_pbr_cfg = bgp->bgp_pbr_cfg;
2932 struct bgp_pbr_interface_head *head;
2933 struct bgp_pbr_interface *pbr_if;
2934
2935 if (!bgp_pbr_cfg)
2936 return;
2937 if (afi == AFI_IP)
2938 head = &(bgp_pbr_cfg->ifaces_by_name_ipv4);
2939 else
2940 head = &(bgp_pbr_cfg->ifaces_by_name_ipv6);
2941 while (!RB_EMPTY(bgp_pbr_interface_head, head)) {
2942 pbr_if = RB_ROOT(bgp_pbr_interface_head, head);
2943 RB_REMOVE(bgp_pbr_interface_head, head, pbr_if);
2944 XFREE(MTYPE_TMP, pbr_if);
2945 }
2946 }