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