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