]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_pbr.c
bgpd: rework enumerate function, handle not values
[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 "bgpd/bgpd.h"
27 #include "bgpd/bgp_pbr.h"
28 #include "bgpd/bgp_debug.h"
29 #include "bgpd/bgp_flowspec_util.h"
30 #include "bgpd/bgp_ecommunity.h"
31 #include "bgpd/bgp_route.h"
32 #include "bgpd/bgp_attr.h"
33 #include "bgpd/bgp_zebra.h"
34 #include "bgpd/bgp_mplsvpn.h"
35 #include "bgpd/bgp_flowspec_private.h"
36
37 DEFINE_MTYPE_STATIC(BGPD, PBR_MATCH_ENTRY, "PBR match entry")
38 DEFINE_MTYPE_STATIC(BGPD, PBR_MATCH, "PBR match")
39 DEFINE_MTYPE_STATIC(BGPD, PBR_ACTION, "PBR action")
40 DEFINE_MTYPE_STATIC(BGPD, PBR, "BGP PBR Context")
41 DEFINE_MTYPE_STATIC(BGPD, PBR_VALMASK, "BGP PBR Val Mask Value")
42
43 RB_GENERATE(bgp_pbr_interface_head, bgp_pbr_interface,
44 id_entry, bgp_pbr_interface_compare);
45 struct bgp_pbr_interface_head ifaces_by_name_ipv4 =
46 RB_INITIALIZER(&ifaces_by_name_ipv4);
47
48 static int bgp_pbr_match_counter_unique;
49 static int bgp_pbr_match_entry_counter_unique;
50 static int bgp_pbr_action_counter_unique;
51 static int bgp_pbr_match_iptable_counter_unique;
52
53 struct bgp_pbr_match_iptable_unique {
54 uint32_t unique;
55 struct bgp_pbr_match *bpm_found;
56 };
57
58 struct bgp_pbr_match_entry_unique {
59 uint32_t unique;
60 struct bgp_pbr_match_entry *bpme_found;
61 };
62
63 struct bgp_pbr_action_unique {
64 uint32_t unique;
65 struct bgp_pbr_action *bpa_found;
66 };
67
68 static int bgp_pbr_action_walkcb(struct hash_backet *backet, void *arg)
69 {
70 struct bgp_pbr_action *bpa = (struct bgp_pbr_action *)backet->data;
71 struct bgp_pbr_action_unique *bpau = (struct bgp_pbr_action_unique *)
72 arg;
73 uint32_t unique = bpau->unique;
74
75 if (bpa->unique == unique) {
76 bpau->bpa_found = bpa;
77 return HASHWALK_ABORT;
78 }
79 return HASHWALK_CONTINUE;
80 }
81
82 static int bgp_pbr_match_entry_walkcb(struct hash_backet *backet, void *arg)
83 {
84 struct bgp_pbr_match_entry *bpme =
85 (struct bgp_pbr_match_entry *)backet->data;
86 struct bgp_pbr_match_entry_unique *bpmeu =
87 (struct bgp_pbr_match_entry_unique *)arg;
88 uint32_t unique = bpmeu->unique;
89
90 if (bpme->unique == unique) {
91 bpmeu->bpme_found = bpme;
92 return HASHWALK_ABORT;
93 }
94 return HASHWALK_CONTINUE;
95 }
96
97 struct bgp_pbr_match_ipsetname {
98 char *ipsetname;
99 struct bgp_pbr_match *bpm_found;
100 };
101
102 static int bgp_pbr_match_pername_walkcb(struct hash_backet *backet, void *arg)
103 {
104 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)backet->data;
105 struct bgp_pbr_match_ipsetname *bpmi =
106 (struct bgp_pbr_match_ipsetname *)arg;
107 char *ipset_name = bpmi->ipsetname;
108
109 if (!strncmp(ipset_name, bpm->ipset_name,
110 ZEBRA_IPSET_NAME_SIZE)) {
111 bpmi->bpm_found = bpm;
112 return HASHWALK_ABORT;
113 }
114 return HASHWALK_CONTINUE;
115 }
116
117 static int bgp_pbr_match_iptable_walkcb(struct hash_backet *backet, void *arg)
118 {
119 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)backet->data;
120 struct bgp_pbr_match_iptable_unique *bpmiu =
121 (struct bgp_pbr_match_iptable_unique *)arg;
122 uint32_t unique = bpmiu->unique;
123
124 if (bpm->unique2 == unique) {
125 bpmiu->bpm_found = bpm;
126 return HASHWALK_ABORT;
127 }
128 return HASHWALK_CONTINUE;
129 }
130
131 struct bgp_pbr_match_unique {
132 uint32_t unique;
133 struct bgp_pbr_match *bpm_found;
134 };
135
136 static int bgp_pbr_match_walkcb(struct hash_backet *backet, void *arg)
137 {
138 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)backet->data;
139 struct bgp_pbr_match_unique *bpmu = (struct bgp_pbr_match_unique *)
140 arg;
141 uint32_t unique = bpmu->unique;
142
143 if (bpm->unique == unique) {
144 bpmu->bpm_found = bpm;
145 return HASHWALK_ABORT;
146 }
147 return HASHWALK_CONTINUE;
148 }
149
150 static int sprintf_bgp_pbr_match_val(char *str, struct bgp_pbr_match_val *mval,
151 const char *prepend)
152 {
153 char *ptr = str;
154
155 if (prepend)
156 ptr += sprintf(ptr, "%s", prepend);
157 else {
158 if (mval->unary_operator & OPERATOR_UNARY_OR)
159 ptr += sprintf(ptr, ", or ");
160 if (mval->unary_operator & OPERATOR_UNARY_AND)
161 ptr += sprintf(ptr, ", and ");
162 }
163 if (mval->compare_operator & OPERATOR_COMPARE_LESS_THAN)
164 ptr += sprintf(ptr, "<");
165 if (mval->compare_operator & OPERATOR_COMPARE_GREATER_THAN)
166 ptr += sprintf(ptr, ">");
167 if (mval->compare_operator & OPERATOR_COMPARE_EQUAL_TO)
168 ptr += sprintf(ptr, "=");
169 if (mval->compare_operator & OPERATOR_COMPARE_EXACT_MATCH)
170 ptr += sprintf(ptr, "match");
171 ptr += sprintf(ptr, " %u", mval->value);
172 return (int)(ptr - str);
173 }
174
175 #define INCREMENT_DISPLAY(_ptr, _cnt) do { \
176 if (_cnt) \
177 (_ptr) += sprintf((_ptr), "; "); \
178 _cnt++; \
179 } while (0)
180
181 /* this structure can be used for port range,
182 * but also for other values range like packet length range
183 */
184 struct bgp_pbr_range_port {
185 uint16_t min_port;
186 uint16_t max_port;
187 };
188
189 /* this structure can be used to filter with a mask
190 * for instance it supports not instructions like for
191 * tcpflags
192 */
193 struct bgp_pbr_val_mask {
194 uint16_t val;
195 uint16_t mask;
196 };
197
198 /* this structure is used to pass instructs
199 * so that BGP can create pbr instructions to ZEBRA
200 */
201 struct bgp_pbr_filter {
202 vrf_id_t vrf_id;
203 struct prefix *src;
204 struct prefix *dst;
205 uint8_t protocol;
206 struct bgp_pbr_range_port *pkt_len;
207 struct bgp_pbr_range_port *src_port;
208 struct bgp_pbr_range_port *dst_port;
209 struct bgp_pbr_val_mask *tcp_flags;
210 struct bgp_pbr_val_mask *dscp;
211 struct bgp_pbr_val_mask *pkt_len_val;
212 struct bgp_pbr_val_mask *fragment;
213 };
214
215 /* this structure is used to contain OR instructions
216 * so that BGP can create multiple pbr instructions
217 * to ZEBRA
218 */
219 struct bgp_pbr_or_filter {
220 struct list *tcpflags;
221 struct list *dscp;
222 struct list *pkt_len;
223 struct list *fragment;
224 struct list *icmp_type;
225 struct list *icmp_code;
226 };
227
228 static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
229 struct bgp_info *binfo,
230 struct bgp_pbr_filter *bpf,
231 struct nexthop *nh,
232 float *rate);
233
234 static bool bgp_pbr_extract_enumerate_unary_opposite(
235 uint8_t unary_operator,
236 struct bgp_pbr_val_mask *and_valmask,
237 struct list *or_valmask, uint32_t value,
238 uint8_t type_entry)
239 {
240 if (unary_operator == OPERATOR_UNARY_AND && and_valmask) {
241 if (type_entry == FLOWSPEC_TCP_FLAGS) {
242 and_valmask->mask |=
243 TCP_HEADER_ALL_FLAGS &
244 ~(value);
245 } else if (type_entry == FLOWSPEC_DSCP ||
246 type_entry == FLOWSPEC_PKT_LEN ||
247 type_entry == FLOWSPEC_FRAGMENT) {
248 and_valmask->val = value;
249 and_valmask->mask = 1; /* inverse */
250 }
251 } else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) {
252 and_valmask = XCALLOC(MTYPE_PBR_VALMASK,
253 sizeof(struct bgp_pbr_val_mask));
254 if (type_entry == FLOWSPEC_TCP_FLAGS) {
255 and_valmask->val = TCP_HEADER_ALL_FLAGS;
256 and_valmask->mask |=
257 TCP_HEADER_ALL_FLAGS &
258 ~(value);
259 } else if (type_entry == FLOWSPEC_DSCP ||
260 type_entry == FLOWSPEC_FRAGMENT ||
261 type_entry == FLOWSPEC_PKT_LEN) {
262 and_valmask->val = value;
263 and_valmask->mask = 1; /* inverse */
264 }
265 listnode_add(or_valmask, and_valmask);
266 } else if (type_entry == FLOWSPEC_ICMP_CODE ||
267 type_entry == FLOWSPEC_ICMP_TYPE)
268 return false;
269 return true;
270 }
271
272 /* TCP : FIN and SYN -> val = ALL; mask = 3
273 * TCP : not (FIN and SYN) -> val = ALL; mask = ALL & ~(FIN|RST)
274 * other variables type: dscp, pkt len, fragment
275 * - value is copied in bgp_pbr_val_mask->val value
276 * - if negate form is identifierd, bgp_pbr_val_mask->mask set to 1
277 */
278 static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
279 int num, uint8_t unary_operator,
280 void *valmask, uint8_t type_entry)
281 {
282 int i = 0;
283 struct bgp_pbr_val_mask *and_valmask = NULL;
284 struct list *or_valmask = NULL;
285 bool ret;
286
287 if (valmask) {
288 if (unary_operator == OPERATOR_UNARY_AND) {
289 and_valmask = (struct bgp_pbr_val_mask *)valmask;
290 memset(and_valmask, 0, sizeof(struct bgp_pbr_val_mask));
291 } else if (unary_operator == OPERATOR_UNARY_OR) {
292 or_valmask = (struct list *)valmask;
293 }
294 }
295 for (i = 0; i < num; i++) {
296 if (i != 0 && list[i].unary_operator !=
297 unary_operator)
298 return false;
299 if (!(list[i].compare_operator &
300 OPERATOR_COMPARE_EQUAL_TO) &&
301 !(list[i].compare_operator &
302 OPERATOR_COMPARE_EXACT_MATCH)) {
303 if ((list[i].compare_operator &
304 OPERATOR_COMPARE_LESS_THAN) &&
305 (list[i].compare_operator &
306 OPERATOR_COMPARE_GREATER_THAN)) {
307 ret = bgp_pbr_extract_enumerate_unary_opposite(
308 unary_operator, and_valmask,
309 or_valmask, list[i].value,
310 type_entry);
311 if (ret == false)
312 return ret;
313 continue;
314 }
315 return false;
316 }
317 if (unary_operator == OPERATOR_UNARY_AND && and_valmask) {
318 if (type_entry == FLOWSPEC_TCP_FLAGS)
319 and_valmask->mask |=
320 TCP_HEADER_ALL_FLAGS & list[i].value;
321 } else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) {
322 and_valmask = XCALLOC(MTYPE_PBR_VALMASK,
323 sizeof(struct bgp_pbr_val_mask));
324 if (type_entry == FLOWSPEC_TCP_FLAGS) {
325 and_valmask->val = TCP_HEADER_ALL_FLAGS;
326 and_valmask->mask |=
327 TCP_HEADER_ALL_FLAGS & list[i].value;
328 } else if (type_entry == FLOWSPEC_DSCP ||
329 type_entry == FLOWSPEC_ICMP_TYPE ||
330 type_entry == FLOWSPEC_ICMP_CODE ||
331 type_entry == FLOWSPEC_FRAGMENT ||
332 type_entry == FLOWSPEC_PKT_LEN)
333 and_valmask->val = list[i].value;
334 listnode_add(or_valmask, and_valmask);
335 }
336 }
337 if (unary_operator == OPERATOR_UNARY_AND && and_valmask
338 && type_entry == FLOWSPEC_TCP_FLAGS)
339 and_valmask->val = TCP_HEADER_ALL_FLAGS;
340 return true;
341 }
342
343 /* if unary operator can either be UNARY_OR/AND/OR-AND.
344 * in the latter case, combinationf of both is not handled
345 */
346 static bool bgp_pbr_extract_enumerate(struct bgp_pbr_match_val list[],
347 int num, uint8_t unary_operator,
348 void *valmask, uint8_t type_entry)
349 {
350 bool ret;
351 uint8_t unary_operator_val = unary_operator;
352 bool double_check = false;
353
354 if ((unary_operator & OPERATOR_UNARY_OR) &&
355 (unary_operator & OPERATOR_UNARY_AND)) {
356 unary_operator_val = OPERATOR_UNARY_AND;
357 double_check = true;
358 } else
359 unary_operator_val = unary_operator;
360 ret = bgp_pbr_extract_enumerate_unary(list, num, unary_operator_val,
361 valmask, type_entry);
362 if (!ret && double_check)
363 ret = bgp_pbr_extract_enumerate_unary(list, num,
364 OPERATOR_UNARY_OR,
365 valmask,
366 type_entry);
367 return ret;
368 }
369
370 /* returns the unary operator that is in the list
371 * return 0 if both operators are used
372 */
373 static uint8_t bgp_pbr_match_val_get_operator(struct bgp_pbr_match_val list[],
374 int num)
375
376 {
377 int i;
378 uint8_t unary_operator = OPERATOR_UNARY_AND;
379
380 for (i = 0; i < num; i++) {
381 if (i == 0)
382 continue;
383 if (list[i].unary_operator & OPERATOR_UNARY_OR)
384 unary_operator = OPERATOR_UNARY_OR;
385 if ((list[i].unary_operator & OPERATOR_UNARY_AND
386 && unary_operator == OPERATOR_UNARY_OR) ||
387 (list[i].unary_operator & OPERATOR_UNARY_OR
388 && unary_operator == OPERATOR_UNARY_AND))
389 return 0;
390 }
391 return unary_operator;
392 }
393
394
395 /* return true if extraction ok
396 */
397 static bool bgp_pbr_extract(struct bgp_pbr_match_val list[],
398 int num,
399 struct bgp_pbr_range_port *range)
400 {
401 int i = 0;
402 bool exact_match = false;
403
404 if (range)
405 memset(range, 0, sizeof(struct bgp_pbr_range_port));
406
407 if (num > 2)
408 return false;
409 for (i = 0; i < num; i++) {
410 if (i != 0 && (list[i].compare_operator ==
411 OPERATOR_COMPARE_EQUAL_TO))
412 return false;
413 if (i == 0 && (list[i].compare_operator ==
414 OPERATOR_COMPARE_EQUAL_TO)) {
415 if (range)
416 range->min_port = list[i].value;
417 exact_match = true;
418 }
419 if (exact_match == true && i > 0)
420 return false;
421 if (list[i].compare_operator ==
422 (OPERATOR_COMPARE_GREATER_THAN +
423 OPERATOR_COMPARE_EQUAL_TO)) {
424 if (range)
425 range->min_port = list[i].value;
426 } else if (list[i].compare_operator ==
427 (OPERATOR_COMPARE_LESS_THAN +
428 OPERATOR_COMPARE_EQUAL_TO)) {
429 if (range)
430 range->max_port = list[i].value;
431 } else if (list[i].compare_operator ==
432 OPERATOR_COMPARE_LESS_THAN) {
433 if (range)
434 range->max_port = list[i].value - 1;
435 } else if (list[i].compare_operator ==
436 OPERATOR_COMPARE_GREATER_THAN) {
437 if (range)
438 range->min_port = list[i].value + 1;
439 }
440 }
441 return true;
442 }
443
444 static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
445 {
446 bool enumerate_icmp = false;
447
448 /* because bgp pbr entry may contain unsupported
449 * combinations, a message will be displayed here if
450 * not supported.
451 * for now, only match/set supported is
452 * - combination src/dst => redirect nexthop [ + rate]
453 * - combination src/dst => redirect VRF [ + rate]
454 * - combination src/dst => drop
455 * - combination srcport + @IP
456 */
457 if (api->match_protocol_num > 1) {
458 if (BGP_DEBUG(pbr, PBR))
459 zlog_debug("BGP: match protocol operations:"
460 "multiple protocols ( %d). ignoring.",
461 api->match_protocol_num);
462 return 0;
463 }
464 if (api->match_protocol_num == 1 &&
465 api->protocol[0].value != PROTOCOL_UDP &&
466 api->protocol[0].value != PROTOCOL_ICMP &&
467 api->protocol[0].value != PROTOCOL_TCP) {
468 if (BGP_DEBUG(pbr, PBR))
469 zlog_debug("BGP: match protocol operations:"
470 "protocol (%d) not supported. ignoring",
471 api->match_protocol_num);
472 return 0;
473 }
474 if (!bgp_pbr_extract(api->src_port, api->match_src_port_num, NULL)) {
475 if (BGP_DEBUG(pbr, PBR))
476 zlog_debug("BGP: match src port operations:"
477 "too complex. ignoring.");
478 return 0;
479 }
480 if (!bgp_pbr_extract(api->dst_port, api->match_dst_port_num, NULL)) {
481 if (BGP_DEBUG(pbr, PBR))
482 zlog_debug("BGP: match dst port operations:"
483 "too complex. ignoring.");
484 return 0;
485 }
486 if (!bgp_pbr_extract_enumerate(api->tcpflags,
487 api->match_tcpflags_num,
488 OPERATOR_UNARY_AND |
489 OPERATOR_UNARY_OR, NULL,
490 FLOWSPEC_TCP_FLAGS)) {
491 if (BGP_DEBUG(pbr, PBR))
492 zlog_debug("BGP: match tcp flags:"
493 "too complex. ignoring.");
494 return 0;
495 }
496 if (!bgp_pbr_extract(api->icmp_type, api->match_icmp_type_num, NULL)) {
497 if (!bgp_pbr_extract_enumerate(api->icmp_type,
498 api->match_icmp_type_num,
499 OPERATOR_UNARY_OR, NULL,
500 FLOWSPEC_ICMP_TYPE)) {
501 if (BGP_DEBUG(pbr, PBR))
502 zlog_debug("BGP: match icmp type operations:"
503 "too complex. ignoring.");
504 return 0;
505 }
506 enumerate_icmp = true;
507 }
508 if (!bgp_pbr_extract(api->icmp_code, api->match_icmp_code_num, NULL)) {
509 if (!bgp_pbr_extract_enumerate(api->icmp_code,
510 api->match_icmp_code_num,
511 OPERATOR_UNARY_OR, NULL,
512 FLOWSPEC_ICMP_CODE)) {
513 if (BGP_DEBUG(pbr, PBR))
514 zlog_debug("BGP: match icmp code operations:"
515 "too complex. ignoring.");
516 return 0;
517 } else if (api->match_icmp_type_num > 1 &&
518 enumerate_icmp == false) {
519 if (BGP_DEBUG(pbr, PBR))
520 zlog_debug("BGP: match icmp code is enumerate"
521 ", and icmp type is not."
522 " too complex. ignoring.");
523 return 0;
524 }
525 }
526 if (!bgp_pbr_extract(api->port, api->match_port_num, NULL)) {
527 if (BGP_DEBUG(pbr, PBR))
528 zlog_debug("BGP: match port operations:"
529 "too complex. ignoring.");
530 return 0;
531 }
532 if (api->match_packet_length_num) {
533 bool ret;
534
535 ret = bgp_pbr_extract(api->packet_length,
536 api->match_packet_length_num, NULL);
537 if (!ret)
538 ret = bgp_pbr_extract_enumerate(api->packet_length,
539 api->match_packet_length_num,
540 OPERATOR_UNARY_OR
541 | OPERATOR_UNARY_AND,
542 NULL, FLOWSPEC_PKT_LEN);
543 if (!ret) {
544 if (BGP_DEBUG(pbr, PBR))
545 zlog_debug("BGP: match packet length operations:"
546 "too complex. ignoring.");
547 return 0;
548 }
549 }
550 if (api->match_dscp_num) {
551 if (!bgp_pbr_extract_enumerate(api->dscp, api->match_dscp_num,
552 OPERATOR_UNARY_OR | OPERATOR_UNARY_AND,
553 NULL, FLOWSPEC_DSCP)) {
554 if (BGP_DEBUG(pbr, PBR))
555 zlog_debug("BGP: match DSCP operations:"
556 "too complex. ignoring.");
557 return 0;
558 }
559 }
560 if (api->match_fragment_num) {
561 char fail_str[64];
562 bool success;
563
564 success = bgp_pbr_extract_enumerate(api->fragment,
565 api->match_fragment_num,
566 OPERATOR_UNARY_OR
567 | OPERATOR_UNARY_AND,
568 NULL, FLOWSPEC_FRAGMENT);
569 if (success) {
570 int i;
571
572 for (i = 0; i < api->match_fragment_num; i++) {
573 if (api->fragment[i].value != 1 &&
574 api->fragment[i].value != 2 &&
575 api->fragment[i].value != 4 &&
576 api->fragment[i].value != 8) {
577 success = false;
578 sprintf(fail_str,
579 "Value not valid (%d) for this implementation",
580 api->fragment[i].value);
581 }
582 }
583 } else
584 sprintf(fail_str, "too complex. ignoring");
585 if (!success) {
586 if (BGP_DEBUG(pbr, PBR))
587 zlog_debug("BGP: match fragment operation (%d) %s",
588 api->match_fragment_num,
589 fail_str);
590 return 0;
591 }
592 }
593
594 /* no combinations with both src_port and dst_port
595 * or port with src_port and dst_port
596 */
597 if (api->match_src_port_num + api->match_dst_port_num +
598 api->match_port_num > 3) {
599 if (BGP_DEBUG(pbr, PBR))
600 zlog_debug("BGP: match multiple port operations:"
601 " too complex. ignoring.");
602 return 0;
603 }
604 if ((api->match_src_port_num || api->match_dst_port_num
605 || api->match_port_num) && (api->match_icmp_type_num
606 || api->match_icmp_code_num)) {
607 if (BGP_DEBUG(pbr, PBR))
608 zlog_debug("BGP: match multiple port/imcp operations:"
609 " too complex. ignoring.");
610 return 0;
611 }
612 if (!(api->match_bitmask & PREFIX_SRC_PRESENT) &&
613 !(api->match_bitmask & PREFIX_DST_PRESENT)) {
614 if (BGP_DEBUG(pbr, PBR)) {
615 bgp_pbr_print_policy_route(api);
616 zlog_debug("BGP: match actions without src"
617 " or dst address can not operate."
618 " ignoring.");
619 }
620 return 0;
621 }
622 return 1;
623 }
624
625 /* return -1 if build or validation failed */
626 static int bgp_pbr_build_and_validate_entry(struct prefix *p,
627 struct bgp_info *info,
628 struct bgp_pbr_entry_main *api)
629 {
630 int ret;
631 int i, action_count = 0;
632 struct ecommunity *ecom;
633 struct ecommunity_val *ecom_eval;
634 struct bgp_pbr_entry_action *api_action;
635 struct prefix *src = NULL, *dst = NULL;
636 int valid_prefix = 0;
637 afi_t afi = AFI_IP;
638
639 /* extract match from flowspec entries */
640 ret = bgp_flowspec_match_rules_fill((uint8_t *)p->u.prefix_flowspec.ptr,
641 p->u.prefix_flowspec.prefixlen, api);
642 if (ret < 0)
643 return -1;
644 /* extract actiosn from flowspec ecom list */
645 if (info && info->attr && info->attr->ecommunity) {
646 ecom = info->attr->ecommunity;
647 for (i = 0; i < ecom->size; i++) {
648 ecom_eval = (struct ecommunity_val *)
649 (ecom->val + (i * ECOMMUNITY_SIZE));
650 action_count++;
651 if (action_count > ACTIONS_MAX_NUM) {
652 if (BGP_DEBUG(pbr, PBR_ERROR))
653 zlog_err("%s: flowspec actions exceeds limit (max %u)",
654 __func__, action_count);
655 break;
656 }
657 api_action = &api->actions[action_count - 1];
658
659 if ((ecom_eval->val[1] ==
660 (char)ECOMMUNITY_REDIRECT_VRF) &&
661 (ecom_eval->val[0] ==
662 (char)ECOMMUNITY_ENCODE_TRANS_EXP ||
663 ecom_eval->val[0] ==
664 (char)ECOMMUNITY_EXTENDED_COMMUNITY_PART_2 ||
665 ecom_eval->val[0] ==
666 (char)ECOMMUNITY_EXTENDED_COMMUNITY_PART_3)) {
667 struct ecommunity *eckey = ecommunity_new();
668 struct ecommunity_val ecom_copy;
669
670 memcpy(&ecom_copy, ecom_eval,
671 sizeof(struct ecommunity_val));
672 ecom_copy.val[0] &=
673 ~ECOMMUNITY_ENCODE_TRANS_EXP;
674 ecom_copy.val[1] = ECOMMUNITY_ROUTE_TARGET;
675 ecommunity_add_val(eckey, &ecom_copy);
676
677 api_action->action = ACTION_REDIRECT;
678 api_action->u.redirect_vrf =
679 get_first_vrf_for_redirect_with_rt(
680 eckey);
681 ecommunity_free(&eckey);
682 } else if ((ecom_eval->val[0] ==
683 (char)ECOMMUNITY_ENCODE_REDIRECT_IP_NH) &&
684 (ecom_eval->val[1] ==
685 (char)ECOMMUNITY_REDIRECT_IP_NH)) {
686 api_action->action = ACTION_REDIRECT_IP;
687 api_action->u.zr.redirect_ip_v4.s_addr =
688 info->attr->nexthop.s_addr;
689 api_action->u.zr.duplicate = ecom_eval->val[7];
690 } else {
691 if (ecom_eval->val[0] !=
692 (char)ECOMMUNITY_ENCODE_TRANS_EXP)
693 continue;
694 ret = ecommunity_fill_pbr_action(ecom_eval,
695 api_action);
696 if (ret != 0)
697 continue;
698 }
699 api->action_num++;
700 }
701 }
702
703 /* validate if incoming matc/action is compatible
704 * with our policy routing engine
705 */
706 if (!bgp_pbr_validate_policy_route(api))
707 return -1;
708
709 /* check inconsistency in the match rule */
710 if (api->match_bitmask & PREFIX_SRC_PRESENT) {
711 src = &api->src_prefix;
712 afi = family2afi(src->family);
713 valid_prefix = 1;
714 }
715 if (api->match_bitmask & PREFIX_DST_PRESENT) {
716 dst = &api->dst_prefix;
717 if (valid_prefix && afi != family2afi(dst->family)) {
718 if (BGP_DEBUG(pbr, PBR)) {
719 bgp_pbr_print_policy_route(api);
720 zlog_debug("%s: inconsistency:"
721 " no match for afi src and dst (%u/%u)",
722 __func__, afi, family2afi(dst->family));
723 }
724 return -1;
725 }
726 }
727 return 0;
728 }
729
730 static void bgp_pbr_match_entry_free(void *arg)
731 {
732 struct bgp_pbr_match_entry *bpme;
733
734 bpme = (struct bgp_pbr_match_entry *)arg;
735
736 if (bpme->installed) {
737 bgp_send_pbr_ipset_entry_match(bpme, false);
738 bpme->installed = false;
739 bpme->backpointer = NULL;
740 }
741 XFREE(MTYPE_PBR_MATCH_ENTRY, bpme);
742 }
743
744 static void bgp_pbr_match_free(void *arg)
745 {
746 struct bgp_pbr_match *bpm;
747
748 bpm = (struct bgp_pbr_match *)arg;
749
750 hash_clean(bpm->entry_hash, bgp_pbr_match_entry_free);
751
752 if (hashcount(bpm->entry_hash) == 0) {
753 /* delete iptable entry first */
754 /* then delete ipset match */
755 if (bpm->installed) {
756 if (bpm->installed_in_iptable) {
757 bgp_send_pbr_iptable(bpm->action,
758 bpm, false);
759 bpm->installed_in_iptable = false;
760 bpm->action->refcnt--;
761 }
762 bgp_send_pbr_ipset_match(bpm, false);
763 bpm->installed = false;
764 bpm->action = NULL;
765 }
766 }
767 hash_free(bpm->entry_hash);
768
769 XFREE(MTYPE_PBR_MATCH, bpm);
770 }
771
772 static void *bgp_pbr_match_alloc_intern(void *arg)
773 {
774 struct bgp_pbr_match *bpm, *new;
775
776 bpm = (struct bgp_pbr_match *)arg;
777
778 new = XCALLOC(MTYPE_PBR_MATCH, sizeof(*new));
779 memcpy(new, bpm, sizeof(*bpm));
780
781 return new;
782 }
783
784 static void bgp_pbr_action_free(void *arg)
785 {
786 struct bgp_pbr_action *bpa;
787
788 bpa = (struct bgp_pbr_action *)arg;
789
790 if (bpa->refcnt == 0) {
791 if (bpa->installed && bpa->table_id != 0) {
792 bgp_send_pbr_rule_action(bpa, false);
793 bgp_zebra_announce_default(bpa->bgp, &(bpa->nh),
794 AFI_IP,
795 bpa->table_id,
796 false);
797 bpa->installed = false;
798 }
799 }
800 XFREE(MTYPE_PBR_ACTION, bpa);
801 }
802
803 static void *bgp_pbr_action_alloc_intern(void *arg)
804 {
805 struct bgp_pbr_action *bpa, *new;
806
807 bpa = (struct bgp_pbr_action *)arg;
808
809 new = XCALLOC(MTYPE_PBR_ACTION, sizeof(*new));
810
811 memcpy(new, bpa, sizeof(*bpa));
812
813 return new;
814 }
815
816 static void *bgp_pbr_match_entry_alloc_intern(void *arg)
817 {
818 struct bgp_pbr_match_entry *bpme, *new;
819
820 bpme = (struct bgp_pbr_match_entry *)arg;
821
822 new = XCALLOC(MTYPE_PBR_MATCH_ENTRY, sizeof(*new));
823
824 memcpy(new, bpme, sizeof(*bpme));
825
826 return new;
827 }
828
829 uint32_t bgp_pbr_match_hash_key(void *arg)
830 {
831 struct bgp_pbr_match *pbm = (struct bgp_pbr_match *)arg;
832 uint32_t key;
833
834 key = jhash_1word(pbm->vrf_id, 0x4312abde);
835 key = jhash_1word(pbm->flags, key);
836 key = jhash_1word(pbm->pkt_len_min, key);
837 key = jhash_1word(pbm->pkt_len_max, key);
838 key = jhash_1word(pbm->tcp_flags, key);
839 key = jhash_1word(pbm->tcp_mask_flags, key);
840 key = jhash_1word(pbm->dscp_value, key);
841 key = jhash_1word(pbm->fragment, key);
842 return jhash_1word(pbm->type, key);
843 }
844
845 int bgp_pbr_match_hash_equal(const void *arg1, const void *arg2)
846 {
847 const struct bgp_pbr_match *r1, *r2;
848
849 r1 = (const struct bgp_pbr_match *)arg1;
850 r2 = (const struct bgp_pbr_match *)arg2;
851
852 if (r1->vrf_id != r2->vrf_id)
853 return 0;
854
855 if (r1->type != r2->type)
856 return 0;
857
858 if (r1->flags != r2->flags)
859 return 0;
860
861 if (r1->action != r2->action)
862 return 0;
863
864 if (r1->pkt_len_min != r2->pkt_len_min)
865 return 0;
866
867 if (r1->pkt_len_max != r2->pkt_len_max)
868 return 0;
869
870 if (r1->tcp_flags != r2->tcp_flags)
871 return 0;
872
873 if (r1->tcp_mask_flags != r2->tcp_mask_flags)
874 return 0;
875
876 if (r1->dscp_value != r2->dscp_value)
877 return 0;
878
879 if (r1->fragment != r2->fragment)
880 return 0;
881 return 1;
882 }
883
884 uint32_t bgp_pbr_match_entry_hash_key(void *arg)
885 {
886 struct bgp_pbr_match_entry *pbme;
887 uint32_t key;
888
889 pbme = (struct bgp_pbr_match_entry *)arg;
890 key = prefix_hash_key(&pbme->src);
891 key = jhash_1word(prefix_hash_key(&pbme->dst), key);
892 key = jhash(&pbme->dst_port_min, 2, key);
893 key = jhash(&pbme->src_port_min, 2, key);
894 key = jhash(&pbme->dst_port_max, 2, key);
895 key = jhash(&pbme->src_port_max, 2, key);
896 key = jhash(&pbme->proto, 1, key);
897
898 return key;
899 }
900
901 int bgp_pbr_match_entry_hash_equal(const void *arg1, const void *arg2)
902 {
903 const struct bgp_pbr_match_entry *r1, *r2;
904
905 r1 = (const struct bgp_pbr_match_entry *)arg1;
906 r2 = (const struct bgp_pbr_match_entry *)arg2;
907
908 /* on updates, comparing
909 * backpointer is not necessary
910 */
911
912 /* unique value is self calculated
913 */
914
915 /* rate is ignored for now
916 */
917
918 if (!prefix_same(&r1->src, &r2->src))
919 return 0;
920
921 if (!prefix_same(&r1->dst, &r2->dst))
922 return 0;
923
924 if (r1->src_port_min != r2->src_port_min)
925 return 0;
926
927 if (r1->dst_port_min != r2->dst_port_min)
928 return 0;
929
930 if (r1->src_port_max != r2->src_port_max)
931 return 0;
932
933 if (r1->dst_port_max != r2->dst_port_max)
934 return 0;
935
936 if (r1->proto != r2->proto)
937 return 0;
938
939 return 1;
940 }
941
942 uint32_t bgp_pbr_action_hash_key(void *arg)
943 {
944 struct bgp_pbr_action *pbra;
945 uint32_t key;
946
947 pbra = (struct bgp_pbr_action *)arg;
948 key = jhash_1word(pbra->table_id, 0x4312abde);
949 key = jhash_1word(pbra->fwmark, key);
950 return key;
951 }
952
953 int bgp_pbr_action_hash_equal(const void *arg1, const void *arg2)
954 {
955 const struct bgp_pbr_action *r1, *r2;
956
957 r1 = (const struct bgp_pbr_action *)arg1;
958 r2 = (const struct bgp_pbr_action *)arg2;
959
960 /* unique value is self calculated
961 * table and fwmark is self calculated
962 * rate is ignored
963 */
964 if (r1->vrf_id != r2->vrf_id)
965 return 0;
966
967 if (memcmp(&r1->nh, &r2->nh, sizeof(struct nexthop)))
968 return 0;
969 return 1;
970 }
971
972 struct bgp_pbr_action *bgp_pbr_action_rule_lookup(vrf_id_t vrf_id,
973 uint32_t unique)
974 {
975 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
976 struct bgp_pbr_action_unique bpau;
977
978 if (!bgp || unique == 0)
979 return NULL;
980 bpau.unique = unique;
981 bpau.bpa_found = NULL;
982 hash_walk(bgp->pbr_action_hash, bgp_pbr_action_walkcb, &bpau);
983 return bpau.bpa_found;
984 }
985
986 struct bgp_pbr_match *bgp_pbr_match_ipset_lookup(vrf_id_t vrf_id,
987 uint32_t unique)
988 {
989 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
990 struct bgp_pbr_match_unique bpmu;
991
992 if (!bgp || unique == 0)
993 return NULL;
994 bpmu.unique = unique;
995 bpmu.bpm_found = NULL;
996 hash_walk(bgp->pbr_match_hash, bgp_pbr_match_walkcb, &bpmu);
997 return bpmu.bpm_found;
998 }
999
1000 struct bgp_pbr_match_entry *bgp_pbr_match_ipset_entry_lookup(vrf_id_t vrf_id,
1001 char *ipset_name,
1002 uint32_t unique)
1003 {
1004 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1005 struct bgp_pbr_match_entry_unique bpmeu;
1006 struct bgp_pbr_match_ipsetname bpmi;
1007
1008 if (!bgp || unique == 0)
1009 return NULL;
1010 bpmi.ipsetname = XCALLOC(MTYPE_TMP, ZEBRA_IPSET_NAME_SIZE);
1011 snprintf(bpmi.ipsetname, ZEBRA_IPSET_NAME_SIZE, "%s", ipset_name);
1012 bpmi.bpm_found = NULL;
1013 hash_walk(bgp->pbr_match_hash, bgp_pbr_match_pername_walkcb, &bpmi);
1014 XFREE(MTYPE_TMP, bpmi.ipsetname);
1015 if (!bpmi.bpm_found)
1016 return NULL;
1017 bpmeu.bpme_found = NULL;
1018 bpmeu.unique = unique;
1019 hash_walk(bpmi.bpm_found->entry_hash,
1020 bgp_pbr_match_entry_walkcb, &bpmeu);
1021 return bpmeu.bpme_found;
1022 }
1023
1024 struct bgp_pbr_match *bgp_pbr_match_iptable_lookup(vrf_id_t vrf_id,
1025 uint32_t unique)
1026 {
1027 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1028 struct bgp_pbr_match_iptable_unique bpmiu;
1029
1030 if (!bgp || unique == 0)
1031 return NULL;
1032 bpmiu.unique = unique;
1033 bpmiu.bpm_found = NULL;
1034 hash_walk(bgp->pbr_match_hash, bgp_pbr_match_iptable_walkcb, &bpmiu);
1035 return bpmiu.bpm_found;
1036 }
1037
1038 void bgp_pbr_cleanup(struct bgp *bgp)
1039 {
1040 if (bgp->pbr_match_hash) {
1041 hash_clean(bgp->pbr_match_hash, bgp_pbr_match_free);
1042 hash_free(bgp->pbr_match_hash);
1043 bgp->pbr_match_hash = NULL;
1044 }
1045 if (bgp->pbr_action_hash) {
1046 hash_clean(bgp->pbr_action_hash, bgp_pbr_action_free);
1047 hash_free(bgp->pbr_action_hash);
1048 bgp->pbr_action_hash = NULL;
1049 }
1050 if (bgp->bgp_pbr_cfg == NULL)
1051 return;
1052 bgp_pbr_reset(bgp, AFI_IP);
1053 XFREE(MTYPE_PBR, bgp->bgp_pbr_cfg);
1054 bgp->bgp_pbr_cfg = NULL;
1055 }
1056
1057 void bgp_pbr_init(struct bgp *bgp)
1058 {
1059 bgp->pbr_match_hash =
1060 hash_create_size(8, bgp_pbr_match_hash_key,
1061 bgp_pbr_match_hash_equal,
1062 "Match Hash");
1063 bgp->pbr_action_hash =
1064 hash_create_size(8, bgp_pbr_action_hash_key,
1065 bgp_pbr_action_hash_equal,
1066 "Match Hash Entry");
1067
1068 bgp->bgp_pbr_cfg = XCALLOC(MTYPE_PBR, sizeof(struct bgp_pbr_config));
1069 bgp->bgp_pbr_cfg->pbr_interface_any_ipv4 = true;
1070 }
1071
1072 void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api)
1073 {
1074 int i = 0;
1075 char return_string[512];
1076 char *ptr = return_string;
1077 char buff[64];
1078 int nb_items = 0;
1079
1080 ptr += sprintf(ptr, "MATCH : ");
1081 if (api->match_bitmask & PREFIX_SRC_PRESENT) {
1082 struct prefix *p = &(api->src_prefix);
1083
1084 ptr += sprintf(ptr, "@src %s", prefix2str(p, buff, 64));
1085 INCREMENT_DISPLAY(ptr, nb_items);
1086 }
1087 if (api->match_bitmask & PREFIX_DST_PRESENT) {
1088 struct prefix *p = &(api->dst_prefix);
1089
1090 INCREMENT_DISPLAY(ptr, nb_items);
1091 ptr += sprintf(ptr, "@dst %s", prefix2str(p, buff, 64));
1092 }
1093
1094 if (api->match_protocol_num)
1095 INCREMENT_DISPLAY(ptr, nb_items);
1096 for (i = 0; i < api->match_protocol_num; i++)
1097 ptr += sprintf_bgp_pbr_match_val(ptr, &api->protocol[i],
1098 i > 0 ? NULL : "@proto ");
1099
1100 if (api->match_src_port_num)
1101 INCREMENT_DISPLAY(ptr, nb_items);
1102 for (i = 0; i < api->match_src_port_num; i++)
1103 ptr += sprintf_bgp_pbr_match_val(ptr, &api->src_port[i],
1104 i > 0 ? NULL : "@srcport ");
1105
1106 if (api->match_dst_port_num)
1107 INCREMENT_DISPLAY(ptr, nb_items);
1108 for (i = 0; i < api->match_dst_port_num; i++)
1109 ptr += sprintf_bgp_pbr_match_val(ptr, &api->dst_port[i],
1110 i > 0 ? NULL : "@dstport ");
1111
1112 if (api->match_port_num)
1113 INCREMENT_DISPLAY(ptr, nb_items);
1114 for (i = 0; i < api->match_port_num; i++)
1115 ptr += sprintf_bgp_pbr_match_val(ptr, &api->port[i],
1116 i > 0 ? NULL : "@port ");
1117
1118 if (api->match_icmp_type_num)
1119 INCREMENT_DISPLAY(ptr, nb_items);
1120 for (i = 0; i < api->match_icmp_type_num; i++)
1121 ptr += sprintf_bgp_pbr_match_val(ptr, &api->icmp_type[i],
1122 i > 0 ? NULL : "@icmptype ");
1123
1124 if (api->match_icmp_code_num)
1125 INCREMENT_DISPLAY(ptr, nb_items);
1126 for (i = 0; i < api->match_icmp_code_num; i++)
1127 ptr += sprintf_bgp_pbr_match_val(ptr, &api->icmp_code[i],
1128 i > 0 ? NULL : "@icmpcode ");
1129
1130 if (api->match_packet_length_num)
1131 INCREMENT_DISPLAY(ptr, nb_items);
1132 for (i = 0; i < api->match_packet_length_num; i++)
1133 ptr += sprintf_bgp_pbr_match_val(ptr, &api->packet_length[i],
1134 i > 0 ? NULL : "@plen ");
1135
1136 if (api->match_dscp_num)
1137 INCREMENT_DISPLAY(ptr, nb_items);
1138 for (i = 0; i < api->match_dscp_num; i++)
1139 ptr += sprintf_bgp_pbr_match_val(ptr, &api->dscp[i],
1140 i > 0 ? NULL : "@dscp ");
1141
1142 if (api->match_tcpflags_num)
1143 INCREMENT_DISPLAY(ptr, nb_items);
1144 for (i = 0; i < api->match_tcpflags_num; i++)
1145 ptr += sprintf_bgp_pbr_match_val(ptr, &api->tcpflags[i],
1146 i > 0 ? NULL : "@tcpflags ");
1147
1148 if (api->match_fragment_num)
1149 INCREMENT_DISPLAY(ptr, nb_items);
1150 for (i = 0; i < api->match_fragment_num; i++)
1151 ptr += sprintf_bgp_pbr_match_val(ptr, &api->fragment[i],
1152 i > 0 ? NULL : "@fragment ");
1153 if (!nb_items)
1154 ptr = return_string;
1155 else
1156 ptr += sprintf(ptr, "; ");
1157 if (api->action_num)
1158 ptr += sprintf(ptr, "SET : ");
1159 nb_items = 0;
1160 for (i = 0; i < api->action_num; i++) {
1161 switch (api->actions[i].action) {
1162 case ACTION_TRAFFICRATE:
1163 INCREMENT_DISPLAY(ptr, nb_items);
1164 ptr += sprintf(ptr, "@set rate %f",
1165 api->actions[i].u.r.rate);
1166 break;
1167 case ACTION_TRAFFIC_ACTION:
1168 INCREMENT_DISPLAY(ptr, nb_items);
1169 ptr += sprintf(ptr, "@action ");
1170 if (api->actions[i].u.za.filter
1171 & TRAFFIC_ACTION_TERMINATE)
1172 ptr += sprintf(ptr,
1173 " terminate (apply filter(s))");
1174 if (api->actions[i].u.za.filter
1175 & TRAFFIC_ACTION_DISTRIBUTE)
1176 ptr += sprintf(ptr, " distribute");
1177 if (api->actions[i].u.za.filter
1178 & TRAFFIC_ACTION_SAMPLE)
1179 ptr += sprintf(ptr, " sample");
1180 break;
1181 case ACTION_REDIRECT_IP:
1182 INCREMENT_DISPLAY(ptr, nb_items);
1183 char local_buff[INET_ADDRSTRLEN];
1184
1185 if (inet_ntop(AF_INET,
1186 &api->actions[i].u.zr.redirect_ip_v4,
1187 local_buff, INET_ADDRSTRLEN) != NULL)
1188 ptr += sprintf(ptr,
1189 "@redirect ip nh %s", local_buff);
1190 break;
1191 case ACTION_REDIRECT:
1192 INCREMENT_DISPLAY(ptr, nb_items);
1193 ptr += sprintf(ptr, "@redirect vrf %u",
1194 api->actions[i].u.redirect_vrf);
1195 break;
1196 case ACTION_MARKING:
1197 INCREMENT_DISPLAY(ptr, nb_items);
1198 ptr += sprintf(ptr, "@set dscp %u",
1199 api->actions[i].u.marking_dscp);
1200 break;
1201 default:
1202 break;
1203 }
1204 }
1205 zlog_info("%s", return_string);
1206 }
1207
1208 static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa,
1209 struct bgp_pbr_match *bpm,
1210 struct bgp_pbr_match_entry *bpme)
1211 {
1212 /* if bpme is null, bpm is also null
1213 */
1214 if (bpme == NULL)
1215 return;
1216 /* ipset del entry */
1217 if (bpme->installed) {
1218 bgp_send_pbr_ipset_entry_match(bpme, false);
1219 bpme->installed = false;
1220 bpme->backpointer = NULL;
1221 if (bpme->bgp_info) {
1222 struct bgp_info *bgp_info;
1223 struct bgp_info_extra *extra;
1224
1225 /* unlink bgp_info to bpme */
1226 bgp_info = (struct bgp_info *)bpme->bgp_info;
1227 extra = bgp_info_extra_get(bgp_info);
1228 extra->bgp_fs_pbr = NULL;
1229 bpme->bgp_info = NULL;
1230 }
1231 }
1232 hash_release(bpm->entry_hash, bpme);
1233 if (hashcount(bpm->entry_hash) == 0) {
1234 /* delete iptable entry first */
1235 /* then delete ipset match */
1236 if (bpm->installed) {
1237 if (bpm->installed_in_iptable) {
1238 bgp_send_pbr_iptable(bpm->action,
1239 bpm, false);
1240 bpm->installed_in_iptable = false;
1241 bpm->action->refcnt--;
1242 }
1243 bgp_send_pbr_ipset_match(bpm, false);
1244 bpm->installed = false;
1245 bpm->action = NULL;
1246 }
1247 hash_release(bgp->pbr_match_hash, bpm);
1248 /* XXX release pbr_match_action if not used
1249 * note that drop does not need to call send_pbr_action
1250 */
1251 }
1252 if (bpa->refcnt == 0) {
1253 if (bpa->installed && bpa->table_id != 0) {
1254 bgp_send_pbr_rule_action(bpa, false);
1255 bgp_zebra_announce_default(bpa->bgp, &(bpa->nh),
1256 AFI_IP,
1257 bpa->table_id,
1258 false);
1259 bpa->installed = false;
1260 }
1261 }
1262 }
1263
1264 struct bgp_pbr_match_entry_remain {
1265 struct bgp_pbr_match_entry *bpme_to_match;
1266 struct bgp_pbr_match_entry *bpme_found;
1267 };
1268
1269 static int bgp_pbr_get_remaining_entry(struct hash_backet *backet, void *arg)
1270 {
1271 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)backet->data;
1272 struct bgp_pbr_match_entry_remain *bpmer =
1273 (struct bgp_pbr_match_entry_remain *)arg;
1274 struct bgp_pbr_match *bpm_temp;
1275 struct bgp_pbr_match_entry *bpme = bpmer->bpme_to_match;
1276
1277 if (!bpme->backpointer ||
1278 bpm == bpme->backpointer ||
1279 bpme->backpointer->action == bpm->action)
1280 return HASHWALK_CONTINUE;
1281 /* ensure bpm other characteristics are equal */
1282 bpm_temp = bpme->backpointer;
1283 if (bpm_temp->vrf_id != bpm->vrf_id ||
1284 bpm_temp->type != bpm->type ||
1285 bpm_temp->flags != bpm->flags)
1286 return HASHWALK_CONTINUE;
1287
1288 /* look for remaining bpme */
1289 bpmer->bpme_found = hash_lookup(bpm->entry_hash, bpme);
1290 if (!bpmer->bpme_found)
1291 return HASHWALK_CONTINUE;
1292 return HASHWALK_ABORT;
1293 }
1294
1295 static void bgp_pbr_policyroute_remove_from_zebra_unit(struct bgp *bgp,
1296 struct bgp_info *binfo,
1297 struct bgp_pbr_filter *bpf)
1298 {
1299 struct bgp_pbr_match temp;
1300 struct bgp_pbr_match_entry temp2;
1301 struct bgp_pbr_match *bpm;
1302 struct bgp_pbr_match_entry *bpme;
1303 struct bgp_pbr_match_entry_remain bpmer;
1304 struct bgp_pbr_range_port *src_port;
1305 struct bgp_pbr_range_port *dst_port;
1306 struct bgp_pbr_range_port *pkt_len;
1307
1308 if (!bpf)
1309 return;
1310 src_port = bpf->src_port;
1311 dst_port = bpf->dst_port;
1312 pkt_len = bpf->pkt_len;
1313
1314 /* as we don't know information from EC
1315 * look for bpm that have the bpm
1316 * with vrf_id characteristics
1317 */
1318 memset(&temp2, 0, sizeof(temp2));
1319 memset(&temp, 0, sizeof(temp));
1320 if (bpf->src) {
1321 temp.flags |= MATCH_IP_SRC_SET;
1322 prefix_copy(&temp2.src, bpf->src);
1323 } else
1324 temp2.src.family = AF_INET;
1325 if (bpf->dst) {
1326 temp.flags |= MATCH_IP_DST_SET;
1327 prefix_copy(&temp2.dst, bpf->dst);
1328 } else
1329 temp2.dst.family = AF_INET;
1330 if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
1331 if (bpf->protocol == IPPROTO_ICMP)
1332 temp.flags |= MATCH_ICMP_SET;
1333 temp.flags |= MATCH_PORT_SRC_SET;
1334 temp2.src_port_min = src_port->min_port;
1335 if (src_port->max_port) {
1336 temp.flags |= MATCH_PORT_SRC_RANGE_SET;
1337 temp2.src_port_max = src_port->max_port;
1338 }
1339 }
1340 if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
1341 if (bpf->protocol == IPPROTO_ICMP)
1342 temp.flags |= MATCH_ICMP_SET;
1343 temp.flags |= MATCH_PORT_DST_SET;
1344 temp2.dst_port_min = dst_port->min_port;
1345 if (dst_port->max_port) {
1346 temp.flags |= MATCH_PORT_DST_RANGE_SET;
1347 temp2.dst_port_max = dst_port->max_port;
1348 }
1349 }
1350 temp2.proto = bpf->protocol;
1351
1352 if (pkt_len) {
1353 temp.pkt_len_min = pkt_len->min_port;
1354 if (pkt_len->max_port)
1355 temp.pkt_len_max = pkt_len->max_port;
1356 } else if (bpf->pkt_len_val) {
1357 if (bpf->pkt_len_val->mask)
1358 temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
1359 temp.pkt_len_min = bpf->pkt_len_val->val;
1360 }
1361 if (bpf->tcp_flags) {
1362 temp.tcp_flags = bpf->tcp_flags->val;
1363 temp.tcp_mask_flags = bpf->tcp_flags->mask;
1364 }
1365 if (bpf->dscp) {
1366 if (bpf->dscp->mask)
1367 temp.flags |= MATCH_DSCP_INVERSE_SET;
1368 else
1369 temp.flags |= MATCH_DSCP_SET;
1370 temp.dscp_value = bpf->dscp->val;
1371 }
1372 if (bpf->fragment) {
1373 if (bpf->fragment->mask)
1374 temp.flags |= MATCH_FRAGMENT_INVERSE_SET;
1375 temp.fragment = bpf->fragment->val;
1376 }
1377
1378 if (bpf->src == NULL || bpf->dst == NULL) {
1379 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
1380 temp.type = IPSET_NET_PORT;
1381 else
1382 temp.type = IPSET_NET;
1383 } else {
1384 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
1385 temp.type = IPSET_NET_PORT_NET;
1386 else
1387 temp.type = IPSET_NET_NET;
1388 }
1389 if (bpf->vrf_id == VRF_UNKNOWN) /* XXX case BGP destroy */
1390 temp.vrf_id = 0;
1391 else
1392 temp.vrf_id = bpf->vrf_id;
1393 bpme = &temp2;
1394 bpm = &temp;
1395 bpme->backpointer = bpm;
1396 /* right now, a previous entry may already exist
1397 * flush previous entry if necessary
1398 */
1399 bpmer.bpme_to_match = bpme;
1400 bpmer.bpme_found = NULL;
1401 hash_walk(bgp->pbr_match_hash, bgp_pbr_get_remaining_entry, &bpmer);
1402 if (bpmer.bpme_found) {
1403 static struct bgp_pbr_match *local_bpm;
1404 static struct bgp_pbr_action *local_bpa;
1405
1406 local_bpm = bpmer.bpme_found->backpointer;
1407 local_bpa = local_bpm->action;
1408 bgp_pbr_flush_entry(bgp, local_bpa,
1409 local_bpm, bpmer.bpme_found);
1410 }
1411 }
1412
1413 static uint8_t bgp_pbr_next_type_entry(uint8_t type_entry)
1414 {
1415 if (type_entry == FLOWSPEC_TCP_FLAGS)
1416 return FLOWSPEC_DSCP;
1417 if (type_entry == FLOWSPEC_DSCP)
1418 return FLOWSPEC_PKT_LEN;
1419 if (type_entry == FLOWSPEC_PKT_LEN)
1420 return FLOWSPEC_FRAGMENT;
1421 if (type_entry == FLOWSPEC_FRAGMENT)
1422 return FLOWSPEC_ICMP_TYPE;
1423 return 0;
1424 }
1425
1426 static void bgp_pbr_icmp_action(struct bgp *bgp,
1427 struct bgp_info *binfo,
1428 struct bgp_pbr_filter *bpf,
1429 struct bgp_pbr_or_filter *bpof,
1430 bool add,
1431 struct nexthop *nh,
1432 float *rate)
1433 {
1434 struct bgp_pbr_range_port srcp, dstp;
1435 struct bgp_pbr_val_mask *icmp_type, *icmp_code;
1436 struct listnode *tnode, *cnode;
1437
1438 if (!bpf)
1439 return;
1440 if (bpf->protocol != IPPROTO_ICMP)
1441 return;
1442 bpf->src_port = &srcp;
1443 bpf->dst_port = &dstp;
1444 /* parse icmp type and lookup appropriate icmp code
1445 * if no icmp code found, create as many entryes as
1446 * there are listed icmp codes for that icmp type
1447 */
1448 if (!bpof->icmp_type) {
1449 srcp.min_port = 0;
1450 srcp.max_port = 255;
1451 for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) {
1452 dstp.min_port = icmp_code->val;
1453 if (add)
1454 bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo,
1455 bpf, nh, rate);
1456 else
1457 bgp_pbr_policyroute_remove_from_zebra_unit(
1458 bgp, binfo, bpf);
1459 }
1460 return;
1461 }
1462 for (ALL_LIST_ELEMENTS_RO(bpof->icmp_type, tnode, icmp_type)) {
1463 srcp.min_port = icmp_type->val;
1464 srcp.max_port = 0;
1465 dstp.max_port = 0;
1466 /* only icmp type. create an entry only with icmp type */
1467 if (!bpof->icmp_code) {
1468 /* icmp type is not one of the above
1469 * forge an entry only based on the icmp type
1470 */
1471 dstp.min_port = 0;
1472 dstp.max_port = 255;
1473 if (add)
1474 bgp_pbr_policyroute_add_to_zebra_unit(
1475 bgp, binfo,
1476 bpf, nh, rate);
1477 else
1478 bgp_pbr_policyroute_remove_from_zebra_unit(bgp,
1479 binfo, bpf);
1480 continue;
1481 }
1482 for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) {
1483 dstp.min_port = icmp_code->val;
1484 if (add)
1485 bgp_pbr_policyroute_add_to_zebra_unit(
1486 bgp, binfo,
1487 bpf, nh, rate);
1488 else
1489 bgp_pbr_policyroute_remove_from_zebra_unit(
1490 bgp, binfo, bpf);
1491 }
1492 }
1493 }
1494
1495 static void bgp_pbr_policyroute_remove_from_zebra_recursive(struct bgp *bgp,
1496 struct bgp_info *binfo,
1497 struct bgp_pbr_filter *bpf,
1498 struct bgp_pbr_or_filter *bpof,
1499 uint8_t type_entry)
1500 {
1501 struct listnode *node, *nnode;
1502 struct bgp_pbr_val_mask *valmask;
1503 uint8_t next_type_entry;
1504 struct list *orig_list;
1505 struct bgp_pbr_val_mask **target_val;
1506
1507 if (type_entry == 0)
1508 return bgp_pbr_policyroute_remove_from_zebra_unit(bgp,
1509 binfo, bpf);
1510 next_type_entry = bgp_pbr_next_type_entry(type_entry);
1511 if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
1512 orig_list = bpof->tcpflags;
1513 target_val = &bpf->tcp_flags;
1514 } else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
1515 orig_list = bpof->dscp;
1516 target_val = &bpf->dscp;
1517 } else if (type_entry == FLOWSPEC_PKT_LEN && bpof->pkt_len) {
1518 orig_list = bpof->pkt_len;
1519 target_val = &bpf->pkt_len_val;
1520 } else if (type_entry == FLOWSPEC_FRAGMENT && bpof->fragment) {
1521 orig_list = bpof->fragment;
1522 target_val = &bpf->fragment;
1523 } else if (type_entry == FLOWSPEC_ICMP_TYPE &&
1524 (bpof->icmp_type || bpof->icmp_code)) {
1525 /* enumerate list for icmp - must be last one */
1526 bgp_pbr_icmp_action(bgp, binfo, bpf, bpof, false, NULL, NULL);
1527 return;
1528 } else {
1529 return bgp_pbr_policyroute_remove_from_zebra_recursive(bgp,
1530 binfo,
1531 bpf, bpof,
1532 next_type_entry);
1533 }
1534 for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
1535 *target_val = valmask;
1536 bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
1537 bpf, bpof,
1538 next_type_entry);
1539 }
1540 }
1541
1542 static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp,
1543 struct bgp_info *binfo,
1544 struct bgp_pbr_filter *bpf,
1545 struct bgp_pbr_or_filter *bpof)
1546 {
1547 if (!bpof)
1548 return bgp_pbr_policyroute_remove_from_zebra_unit(bgp,
1549 binfo,
1550 bpf);
1551 if (bpof->tcpflags)
1552 bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
1553 bpf, bpof,
1554 FLOWSPEC_TCP_FLAGS);
1555 else if (bpof->dscp)
1556 bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
1557 bpf, bpof,
1558 FLOWSPEC_DSCP);
1559 else if (bpof->pkt_len)
1560 bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
1561 bpf, bpof,
1562 FLOWSPEC_PKT_LEN);
1563 else if (bpof->fragment)
1564 bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
1565 bpf, bpof,
1566 FLOWSPEC_FRAGMENT);
1567 else if (bpof->icmp_type || bpof->icmp_code)
1568 bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo,
1569 bpf, bpof,
1570 FLOWSPEC_ICMP_TYPE);
1571 else
1572 bgp_pbr_policyroute_remove_from_zebra_unit(bgp, binfo, bpf);
1573 /* flush bpof */
1574 if (bpof->tcpflags)
1575 list_delete_all_node(bpof->tcpflags);
1576 if (bpof->dscp)
1577 list_delete_all_node(bpof->dscp);
1578 if (bpof->pkt_len)
1579 list_delete_all_node(bpof->pkt_len);
1580 if (bpof->fragment)
1581 list_delete_all_node(bpof->fragment);
1582 }
1583
1584 static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
1585 struct bgp_info *binfo,
1586 struct bgp_pbr_filter *bpf,
1587 struct nexthop *nh,
1588 float *rate)
1589 {
1590 struct bgp_pbr_match temp;
1591 struct bgp_pbr_match_entry temp2;
1592 struct bgp_pbr_match *bpm;
1593 struct bgp_pbr_match_entry *bpme = NULL;
1594 struct bgp_pbr_action temp3;
1595 struct bgp_pbr_action *bpa = NULL;
1596 struct bgp_pbr_match_entry_remain bpmer;
1597 struct bgp_pbr_range_port *src_port;
1598 struct bgp_pbr_range_port *dst_port;
1599 struct bgp_pbr_range_port *pkt_len;
1600
1601 if (!bpf)
1602 return;
1603 src_port = bpf->src_port;
1604 dst_port = bpf->dst_port;
1605 pkt_len = bpf->pkt_len;
1606
1607 if (BGP_DEBUG(zebra, ZEBRA)) {
1608 char bufsrc[64], bufdst[64];
1609 char buffer[64];
1610 int remaining_len = 0;
1611 char protocol_str[16];
1612
1613 protocol_str[0] = '\0';
1614 if (bpf->tcp_flags && bpf->tcp_flags->mask)
1615 bpf->protocol = IPPROTO_TCP;
1616 if (bpf->protocol)
1617 snprintf(protocol_str, sizeof(protocol_str),
1618 "proto %d", bpf->protocol);
1619 buffer[0] = '\0';
1620 if (bpf->protocol == IPPROTO_ICMP && src_port && dst_port)
1621 remaining_len += snprintf(buffer, sizeof(buffer),
1622 "type %d, code %d",
1623 src_port->min_port, dst_port->min_port);
1624 else if (bpf->protocol == IPPROTO_UDP ||
1625 bpf->protocol == IPPROTO_TCP) {
1626
1627 if (src_port && src_port->min_port)
1628 remaining_len += snprintf(buffer,
1629 sizeof(buffer),
1630 "from [%u:%u]",
1631 src_port->min_port,
1632 src_port->max_port ?
1633 src_port->max_port :
1634 src_port->min_port);
1635 if (dst_port && dst_port->min_port)
1636 remaining_len += snprintf(buffer +
1637 remaining_len,
1638 sizeof(buffer)
1639 - remaining_len,
1640 "to [%u:%u]",
1641 dst_port->min_port,
1642 dst_port->max_port ?
1643 dst_port->max_port :
1644 dst_port->min_port);
1645 }
1646 if (pkt_len && (pkt_len->min_port || pkt_len->max_port)) {
1647 remaining_len += snprintf(buffer + remaining_len,
1648 sizeof(buffer)
1649 - remaining_len,
1650 " len [%u:%u]",
1651 pkt_len->min_port,
1652 pkt_len->max_port ?
1653 pkt_len->max_port :
1654 pkt_len->min_port);
1655 } else if (bpf->pkt_len_val) {
1656 remaining_len += snprintf(buffer + remaining_len,
1657 sizeof(buffer)
1658 - remaining_len,
1659 " %s len %u",
1660 bpf->pkt_len_val->mask
1661 ? "!" : "",
1662 bpf->pkt_len_val->val);
1663 }
1664 if (bpf->tcp_flags) {
1665 remaining_len += snprintf(buffer + remaining_len,
1666 sizeof(buffer)
1667 - remaining_len,
1668 "tcpflags %x/%x",
1669 bpf->tcp_flags->val,
1670 bpf->tcp_flags->mask);
1671 }
1672 if (bpf->dscp) {
1673 snprintf(buffer + remaining_len,
1674 sizeof(buffer)
1675 - remaining_len,
1676 "%s dscp %d",
1677 bpf->dscp->mask
1678 ? "!" : "",
1679 bpf->dscp->val);
1680 }
1681 zlog_info("BGP: adding FS PBR from %s to %s, %s %s",
1682 bpf->src == NULL ? "<all>" :
1683 prefix2str(bpf->src, bufsrc, sizeof(bufsrc)),
1684 bpf->dst == NULL ? "<all>" :
1685 prefix2str(bpf->dst, bufdst, sizeof(bufdst)),
1686 protocol_str, buffer);
1687 }
1688 /* look for bpa first */
1689 memset(&temp3, 0, sizeof(temp3));
1690 if (rate)
1691 temp3.rate = *rate;
1692 if (nh)
1693 memcpy(&temp3.nh, nh, sizeof(struct nexthop));
1694 temp3.vrf_id = bpf->vrf_id;
1695 bpa = hash_get(bgp->pbr_action_hash, &temp3,
1696 bgp_pbr_action_alloc_intern);
1697
1698 if (bpa->fwmark == 0) {
1699 /* drop is handled by iptable */
1700 if (nh && nh->type == NEXTHOP_TYPE_BLACKHOLE) {
1701 bpa->table_id = 0;
1702 bpa->installed = true;
1703 } else {
1704 bpa->fwmark = bgp_zebra_tm_get_id();
1705 bpa->table_id = bpa->fwmark;
1706 bpa->installed = false;
1707 }
1708 bpa->bgp = bgp;
1709 bpa->unique = ++bgp_pbr_action_counter_unique;
1710 /* 0 value is forbidden */
1711 bpa->install_in_progress = false;
1712 }
1713
1714 /* then look for bpm */
1715 memset(&temp, 0, sizeof(temp));
1716 temp.vrf_id = bpf->vrf_id;
1717 if (bpf->src)
1718 temp.flags |= MATCH_IP_SRC_SET;
1719 if (bpf->dst)
1720 temp.flags |= MATCH_IP_DST_SET;
1721
1722 if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
1723 if (bpf->protocol == IPPROTO_ICMP)
1724 temp.flags |= MATCH_ICMP_SET;
1725 temp.flags |= MATCH_PORT_SRC_SET;
1726 }
1727 if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
1728 if (bpf->protocol == IPPROTO_ICMP)
1729 temp.flags |= MATCH_ICMP_SET;
1730 temp.flags |= MATCH_PORT_DST_SET;
1731 }
1732 if (src_port && src_port->max_port)
1733 temp.flags |= MATCH_PORT_SRC_RANGE_SET;
1734 if (dst_port && dst_port->max_port)
1735 temp.flags |= MATCH_PORT_DST_RANGE_SET;
1736
1737 if (bpf->src == NULL || bpf->dst == NULL) {
1738 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
1739 temp.type = IPSET_NET_PORT;
1740 else
1741 temp.type = IPSET_NET;
1742 } else {
1743 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
1744 temp.type = IPSET_NET_PORT_NET;
1745 else
1746 temp.type = IPSET_NET_NET;
1747 }
1748 if (pkt_len) {
1749 temp.pkt_len_min = pkt_len->min_port;
1750 if (pkt_len->max_port)
1751 temp.pkt_len_max = pkt_len->max_port;
1752 } else if (bpf->pkt_len_val) {
1753 if (bpf->pkt_len_val->mask)
1754 temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
1755 temp.pkt_len_min = bpf->pkt_len_val->val;
1756 }
1757 if (bpf->tcp_flags) {
1758 temp.tcp_flags = bpf->tcp_flags->val;
1759 temp.tcp_mask_flags = bpf->tcp_flags->mask;
1760 }
1761 if (bpf->dscp) {
1762 if (bpf->dscp->mask)
1763 temp.flags |= MATCH_DSCP_INVERSE_SET;
1764 else
1765 temp.flags |= MATCH_DSCP_SET;
1766 temp.dscp_value = bpf->dscp->val;
1767 }
1768 if (bpf->fragment) {
1769 if (bpf->fragment->mask)
1770 temp.flags |= MATCH_FRAGMENT_INVERSE_SET;
1771 temp.fragment = bpf->fragment->val;
1772 }
1773 temp.action = bpa;
1774 bpm = hash_get(bgp->pbr_match_hash, &temp,
1775 bgp_pbr_match_alloc_intern);
1776
1777 /* new, then self allocate ipset_name and unique */
1778 if (bpm && bpm->unique == 0) {
1779 bpm->unique = ++bgp_pbr_match_counter_unique;
1780 /* 0 value is forbidden */
1781 sprintf(bpm->ipset_name, "match%p", bpm);
1782 bpm->entry_hash = hash_create_size(8,
1783 bgp_pbr_match_entry_hash_key,
1784 bgp_pbr_match_entry_hash_equal,
1785 "Match Entry Hash");
1786 bpm->installed = false;
1787
1788 /* unique2 should be updated too */
1789 bpm->unique2 = ++bgp_pbr_match_iptable_counter_unique;
1790 bpm->installed_in_iptable = false;
1791 bpm->install_in_progress = false;
1792 bpm->install_iptable_in_progress = false;
1793 }
1794
1795 memset(&temp2, 0, sizeof(temp2));
1796 if (bpf->src)
1797 prefix_copy(&temp2.src, bpf->src);
1798 else
1799 temp2.src.family = AF_INET;
1800 if (bpf->dst)
1801 prefix_copy(&temp2.dst, bpf->dst);
1802 else
1803 temp2.dst.family = AF_INET;
1804 temp2.src_port_min = src_port ? src_port->min_port : 0;
1805 temp2.dst_port_min = dst_port ? dst_port->min_port : 0;
1806 temp2.src_port_max = src_port ? src_port->max_port : 0;
1807 temp2.dst_port_max = dst_port ? dst_port->max_port : 0;
1808 temp2.proto = bpf->protocol;
1809 if (bpm)
1810 bpme = hash_get(bpm->entry_hash, &temp2,
1811 bgp_pbr_match_entry_alloc_intern);
1812 if (bpme && bpme->unique == 0) {
1813 bpme->unique = ++bgp_pbr_match_entry_counter_unique;
1814 /* 0 value is forbidden */
1815 bpme->backpointer = bpm;
1816 bpme->installed = false;
1817 bpme->install_in_progress = false;
1818 /* link bgp info to bpme */
1819 bpme->bgp_info = (void *)binfo;
1820 }
1821
1822 /* BGP FS: append entry to zebra
1823 * - policies are not routing entries and as such
1824 * route replace semantics don't necessarily follow
1825 * through to policy entries
1826 * - because of that, not all policing information will be stored
1827 * into zebra. and non selected policies will be suppressed from zebra
1828 * - as consequence, in order to bring consistency
1829 * a policy will be added, then ifan ecmp policy exists,
1830 * it will be suppressed subsequently
1831 */
1832 /* ip rule add */
1833 if (!bpa->installed && !bpa->install_in_progress) {
1834 bgp_send_pbr_rule_action(bpa, true);
1835 bgp_zebra_announce_default(bgp, nh,
1836 AFI_IP, bpa->table_id, true);
1837 }
1838
1839 /* ipset create */
1840 if (bpm && !bpm->installed)
1841 bgp_send_pbr_ipset_match(bpm, true);
1842 /* ipset add */
1843 if (bpme && !bpme->installed)
1844 bgp_send_pbr_ipset_entry_match(bpme, true);
1845
1846 /* iptables */
1847 if (bpm && !bpm->installed_in_iptable)
1848 bgp_send_pbr_iptable(bpa, bpm, true);
1849
1850 /* A previous entry may already exist
1851 * flush previous entry if necessary
1852 */
1853 bpmer.bpme_to_match = bpme;
1854 bpmer.bpme_found = NULL;
1855 hash_walk(bgp->pbr_match_hash, bgp_pbr_get_remaining_entry, &bpmer);
1856 if (bpmer.bpme_found) {
1857 static struct bgp_pbr_match *local_bpm;
1858 static struct bgp_pbr_action *local_bpa;
1859
1860 local_bpm = bpmer.bpme_found->backpointer;
1861 local_bpa = local_bpm->action;
1862 bgp_pbr_flush_entry(bgp, local_bpa,
1863 local_bpm, bpmer.bpme_found);
1864 }
1865
1866
1867 }
1868
1869 static void bgp_pbr_policyroute_add_to_zebra_recursive(struct bgp *bgp,
1870 struct bgp_info *binfo,
1871 struct bgp_pbr_filter *bpf,
1872 struct bgp_pbr_or_filter *bpof,
1873 struct nexthop *nh,
1874 float *rate,
1875 uint8_t type_entry)
1876 {
1877 struct listnode *node, *nnode;
1878 struct bgp_pbr_val_mask *valmask;
1879 uint8_t next_type_entry;
1880 struct list *orig_list;
1881 struct bgp_pbr_val_mask **target_val;
1882
1883 if (type_entry == 0)
1884 return bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf,
1885 nh, rate);
1886 next_type_entry = bgp_pbr_next_type_entry(type_entry);
1887 if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
1888 orig_list = bpof->tcpflags;
1889 target_val = &bpf->tcp_flags;
1890 } else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
1891 orig_list = bpof->dscp;
1892 target_val = &bpf->dscp;
1893 } else if (type_entry == FLOWSPEC_PKT_LEN && bpof->pkt_len) {
1894 orig_list = bpof->pkt_len;
1895 target_val = &bpf->pkt_len_val;
1896 } else if (type_entry == FLOWSPEC_FRAGMENT && bpof->fragment) {
1897 orig_list = bpof->fragment;
1898 target_val = &bpf->fragment;
1899 } else if (type_entry == FLOWSPEC_ICMP_TYPE &&
1900 (bpof->icmp_type || bpof->icmp_code)) {
1901 /* enumerate list for icmp - must be last one */
1902 bgp_pbr_icmp_action(bgp, binfo, bpf, bpof, true, nh, rate);
1903 return;
1904 } else {
1905 return bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
1906 bpf, bpof, nh, rate,
1907 next_type_entry);
1908 }
1909 for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
1910 *target_val = valmask;
1911 bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
1912 bpf, bpof,
1913 nh, rate,
1914 next_type_entry);
1915 }
1916 }
1917
1918 static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
1919 struct bgp_info *binfo,
1920 struct bgp_pbr_filter *bpf,
1921 struct bgp_pbr_or_filter *bpof,
1922 struct nexthop *nh,
1923 float *rate)
1924 {
1925 if (!bpof)
1926 return bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo,
1927 bpf, nh, rate);
1928 if (bpof->tcpflags)
1929 bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
1930 bpf, bpof,
1931 nh, rate,
1932 FLOWSPEC_TCP_FLAGS);
1933 else if (bpof->dscp)
1934 bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
1935 bpf, bpof,
1936 nh, rate,
1937 FLOWSPEC_DSCP);
1938 else if (bpof->pkt_len)
1939 bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
1940 bpf, bpof,
1941 nh, rate,
1942 FLOWSPEC_PKT_LEN);
1943 else if (bpof->fragment)
1944 bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
1945 bpf, bpof,
1946 nh, rate,
1947 FLOWSPEC_FRAGMENT);
1948 else if (bpof->icmp_type || bpof->icmp_code)
1949 bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo,
1950 bpf, bpof, nh, rate,
1951 FLOWSPEC_ICMP_TYPE);
1952 else
1953 bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf,
1954 nh, rate);
1955 /* flush bpof */
1956 if (bpof->tcpflags)
1957 list_delete_all_node(bpof->tcpflags);
1958 if (bpof->dscp)
1959 list_delete_all_node(bpof->dscp);
1960 if (bpof->pkt_len)
1961 list_delete_all_node(bpof->pkt_len);
1962 if (bpof->fragment)
1963 list_delete_all_node(bpof->fragment);
1964 if (bpof->icmp_type)
1965 list_delete_all_node(bpof->icmp_type);
1966 if (bpof->icmp_code)
1967 list_delete_all_node(bpof->icmp_code);
1968 }
1969
1970 static void bgp_pbr_handle_entry(struct bgp *bgp,
1971 struct bgp_info *binfo,
1972 struct bgp_pbr_entry_main *api,
1973 bool add)
1974 {
1975 struct nexthop nh;
1976 int i = 0;
1977 int continue_loop = 1;
1978 float rate = 0;
1979 struct prefix *src = NULL, *dst = NULL;
1980 uint8_t proto = 0;
1981 struct bgp_pbr_range_port *srcp = NULL, *dstp = NULL;
1982 struct bgp_pbr_range_port range, range_icmp_code;
1983 struct bgp_pbr_range_port pkt_len;
1984 struct bgp_pbr_filter bpf;
1985 uint8_t kind_enum;
1986 struct bgp_pbr_or_filter bpof;
1987 struct bgp_pbr_val_mask bpvm;
1988
1989 memset(&nh, 0, sizeof(struct nexthop));
1990 memset(&bpf, 0, sizeof(struct bgp_pbr_filter));
1991 memset(&bpof, 0, sizeof(struct bgp_pbr_or_filter));
1992 if (api->match_bitmask & PREFIX_SRC_PRESENT)
1993 src = &api->src_prefix;
1994 if (api->match_bitmask & PREFIX_DST_PRESENT)
1995 dst = &api->dst_prefix;
1996 memset(&nh, 0, sizeof(struct nexthop));
1997 nh.vrf_id = VRF_UNKNOWN;
1998 if (api->match_protocol_num)
1999 proto = (uint8_t)api->protocol[0].value;
2000 /* if match_port is selected, then either src or dst port will be parsed
2001 * but not both at the same time
2002 */
2003 if (api->match_port_num >= 1) {
2004 bgp_pbr_extract(api->port,
2005 api->match_port_num,
2006 &range);
2007 srcp = dstp = &range;
2008 } else if (api->match_src_port_num >= 1) {
2009 bgp_pbr_extract(api->src_port,
2010 api->match_src_port_num,
2011 &range);
2012 srcp = &range;
2013 dstp = NULL;
2014 } else if (api->match_dst_port_num >= 1) {
2015 bgp_pbr_extract(api->dst_port,
2016 api->match_dst_port_num,
2017 &range);
2018 dstp = &range;
2019 srcp = NULL;
2020 }
2021 if (api->match_icmp_type_num >= 1) {
2022 proto = IPPROTO_ICMP;
2023 if (bgp_pbr_extract(api->icmp_type,
2024 api->match_icmp_type_num,
2025 &range))
2026 srcp = &range;
2027 else {
2028 bpof.icmp_type = list_new();
2029 bgp_pbr_extract_enumerate(api->icmp_type,
2030 api->match_icmp_type_num,
2031 OPERATOR_UNARY_OR,
2032 bpof.icmp_type,
2033 FLOWSPEC_ICMP_TYPE);
2034 }
2035 }
2036 if (api->match_icmp_code_num >= 1) {
2037 proto = IPPROTO_ICMP;
2038 if (bgp_pbr_extract(api->icmp_code,
2039 api->match_icmp_code_num,
2040 &range_icmp_code))
2041 dstp = &range_icmp_code;
2042 else {
2043 bpof.icmp_code = list_new();
2044 bgp_pbr_extract_enumerate(api->icmp_code,
2045 api->match_icmp_code_num,
2046 OPERATOR_UNARY_OR,
2047 bpof.icmp_code,
2048 FLOWSPEC_ICMP_CODE);
2049 }
2050 }
2051
2052 if (api->match_tcpflags_num) {
2053 kind_enum = bgp_pbr_match_val_get_operator(api->tcpflags,
2054 api->match_tcpflags_num);
2055 if (kind_enum == OPERATOR_UNARY_AND) {
2056 bpf.tcp_flags = &bpvm;
2057 bgp_pbr_extract_enumerate(api->tcpflags,
2058 api->match_tcpflags_num,
2059 OPERATOR_UNARY_AND,
2060 bpf.tcp_flags,
2061 FLOWSPEC_TCP_FLAGS);
2062 } else if (kind_enum == OPERATOR_UNARY_OR) {
2063 bpof.tcpflags = list_new();
2064 bgp_pbr_extract_enumerate(api->tcpflags,
2065 api->match_tcpflags_num,
2066 OPERATOR_UNARY_OR,
2067 bpof.tcpflags,
2068 FLOWSPEC_TCP_FLAGS);
2069 }
2070 }
2071 if (api->match_packet_length_num) {
2072 bool ret;
2073
2074 ret = bgp_pbr_extract(api->packet_length,
2075 api->match_packet_length_num,
2076 &pkt_len);
2077 if (ret)
2078 bpf.pkt_len = &pkt_len;
2079 else {
2080 bpof.pkt_len = list_new();
2081 bgp_pbr_extract_enumerate(api->packet_length,
2082 api->match_packet_length_num,
2083 OPERATOR_UNARY_OR,
2084 bpof.pkt_len,
2085 FLOWSPEC_PKT_LEN);
2086 }
2087 }
2088 if (api->match_dscp_num >= 1) {
2089 bpof.dscp = list_new();
2090 bgp_pbr_extract_enumerate(api->dscp, api->match_dscp_num,
2091 OPERATOR_UNARY_OR,
2092 bpof.dscp, FLOWSPEC_DSCP);
2093 }
2094 if (api->match_fragment_num) {
2095 bpof.fragment = list_new();
2096 bgp_pbr_extract_enumerate(api->fragment,
2097 api->match_fragment_num,
2098 OPERATOR_UNARY_OR,
2099 bpof.fragment,
2100 FLOWSPEC_FRAGMENT);
2101 }
2102 bpf.vrf_id = api->vrf_id;
2103 bpf.src = src;
2104 bpf.dst = dst;
2105 bpf.protocol = proto;
2106 bpf.src_port = srcp;
2107 bpf.dst_port = dstp;
2108 if (!add)
2109 return bgp_pbr_policyroute_remove_from_zebra(bgp,
2110 binfo,
2111 &bpf, &bpof);
2112 /* no action for add = true */
2113 for (i = 0; i < api->action_num; i++) {
2114 switch (api->actions[i].action) {
2115 case ACTION_TRAFFICRATE:
2116 /* drop packet */
2117 if (api->actions[i].u.r.rate == 0) {
2118 nh.vrf_id = api->vrf_id;
2119 nh.type = NEXTHOP_TYPE_BLACKHOLE;
2120 bgp_pbr_policyroute_add_to_zebra(bgp, binfo,
2121 &bpf, &bpof,
2122 &nh, &rate);
2123 } else {
2124 /* update rate. can be reentrant */
2125 rate = api->actions[i].u.r.rate;
2126 if (BGP_DEBUG(pbr, PBR)) {
2127 bgp_pbr_print_policy_route(api);
2128 zlog_warn("PBR: ignoring Set action rate %f",
2129 api->actions[i].u.r.rate);
2130 }
2131 }
2132 break;
2133 case ACTION_TRAFFIC_ACTION:
2134 if (api->actions[i].u.za.filter
2135 & TRAFFIC_ACTION_SAMPLE) {
2136 if (BGP_DEBUG(pbr, PBR)) {
2137 bgp_pbr_print_policy_route(api);
2138 zlog_warn("PBR: Sample action Ignored");
2139 }
2140 }
2141 #if 0
2142 if (api->actions[i].u.za.filter
2143 & TRAFFIC_ACTION_DISTRIBUTE) {
2144 if (BGP_DEBUG(pbr, PBR)) {
2145 bgp_pbr_print_policy_route(api);
2146 zlog_warn("PBR: Distribute action Applies");
2147 }
2148 continue_loop = 0;
2149 /* continue forwarding entry as before
2150 * no action
2151 */
2152 }
2153 #endif /* XXX to confirm behaviour of traffic action. for now , ignore */
2154 /* terminate action: run other filters
2155 */
2156 break;
2157 case ACTION_REDIRECT_IP:
2158 nh.type = NEXTHOP_TYPE_IPV4;
2159 nh.gate.ipv4.s_addr =
2160 api->actions[i].u.zr.redirect_ip_v4.s_addr;
2161 nh.vrf_id = api->vrf_id;
2162 bgp_pbr_policyroute_add_to_zebra(bgp, binfo,
2163 &bpf, &bpof,
2164 &nh, &rate);
2165 /* XXX combination with REDIRECT_VRF
2166 * + REDIRECT_NH_IP not done
2167 */
2168 continue_loop = 0;
2169 break;
2170 case ACTION_REDIRECT:
2171 nh.vrf_id = api->actions[i].u.redirect_vrf;
2172 nh.type = NEXTHOP_TYPE_IPV4;
2173 bgp_pbr_policyroute_add_to_zebra(bgp, binfo,
2174 &bpf, &bpof,
2175 &nh, &rate);
2176 continue_loop = 0;
2177 break;
2178 case ACTION_MARKING:
2179 if (BGP_DEBUG(pbr, PBR)) {
2180 bgp_pbr_print_policy_route(api);
2181 zlog_warn("PBR: Set DSCP %u Ignored",
2182 api->actions[i].u.marking_dscp);
2183 }
2184 break;
2185 default:
2186 break;
2187 }
2188 if (continue_loop == 0)
2189 break;
2190 }
2191 }
2192
2193 void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p,
2194 struct bgp_info *info, afi_t afi, safi_t safi,
2195 bool nlri_update)
2196 {
2197 struct bgp_pbr_entry_main api;
2198 struct bgp_info_extra *extra = bgp_info_extra_get(info);
2199
2200 if (afi == AFI_IP6)
2201 return; /* IPv6 not supported */
2202 if (safi != SAFI_FLOWSPEC)
2203 return; /* not supported */
2204 /* Make Zebra API structure. */
2205 memset(&api, 0, sizeof(api));
2206 api.vrf_id = bgp->vrf_id;
2207 api.afi = afi;
2208
2209 if (!bgp_zebra_tm_chunk_obtained()) {
2210 if (BGP_DEBUG(pbr, PBR_ERROR))
2211 zlog_err("%s: table chunk not obtained yet",
2212 __func__);
2213 return;
2214 }
2215 /* already installed */
2216 if (nlri_update && extra->bgp_fs_pbr) {
2217 if (BGP_DEBUG(pbr, PBR_ERROR))
2218 zlog_err("%s: entry %p already installed in bgp pbr",
2219 __func__, info);
2220 return;
2221 }
2222
2223 if (bgp_pbr_build_and_validate_entry(p, info, &api) < 0) {
2224 if (BGP_DEBUG(pbr, PBR_ERROR))
2225 zlog_err("%s: cancel updating entry %p in bgp pbr",
2226 __func__, info);
2227 return;
2228 }
2229 bgp_pbr_handle_entry(bgp, info, &api, nlri_update);
2230 }
2231
2232 int bgp_pbr_interface_compare(const struct bgp_pbr_interface *a,
2233 const struct bgp_pbr_interface *b)
2234 {
2235 return strcmp(a->name, b->name);
2236 }
2237
2238 struct bgp_pbr_interface *bgp_pbr_interface_lookup(const char *name,
2239 struct bgp_pbr_interface_head *head)
2240 {
2241 struct bgp_pbr_interface pbr_if;
2242
2243 strlcpy(pbr_if.name, name, sizeof(pbr_if.name));
2244 return (RB_FIND(bgp_pbr_interface_head,
2245 head, &pbr_if));
2246 }
2247
2248 /* this function resets to the default policy routing
2249 * go back to default status
2250 */
2251 void bgp_pbr_reset(struct bgp *bgp, afi_t afi)
2252 {
2253 struct bgp_pbr_config *bgp_pbr_cfg = bgp->bgp_pbr_cfg;
2254 struct bgp_pbr_interface_head *head;
2255 struct bgp_pbr_interface *pbr_if;
2256
2257 if (!bgp_pbr_cfg || afi != AFI_IP)
2258 return;
2259 head = &(bgp_pbr_cfg->ifaces_by_name_ipv4);
2260
2261 while (!RB_EMPTY(bgp_pbr_interface_head, head)) {
2262 pbr_if = RB_ROOT(bgp_pbr_interface_head, head);
2263 RB_REMOVE(bgp_pbr_interface_head, head, pbr_if);
2264 XFREE(MTYPE_TMP, pbr_if);
2265 }
2266 }