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