Line data Source code
1 : /* zebra routemap.
2 : * Copyright (C) 2006 IBM Corporation
3 : *
4 : * This file is part of GNU Zebra.
5 : *
6 : * GNU Zebra is free software; you can redistribute it and/or modify it
7 : * under the terms of the GNU General Public License as published by the
8 : * Free Software Foundation; either version 2, or (at your option) any
9 : * later version.
10 : *
11 : * GNU Zebra is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License along
17 : * with this program; see the file COPYING; if not, write to the Free Software
18 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : */
20 :
21 : #include <zebra.h>
22 :
23 : #include "memory.h"
24 : #include "prefix.h"
25 : #include "rib.h"
26 : #include "vty.h"
27 : #include "routemap.h"
28 : #include "command.h"
29 : #include "filter.h"
30 : #include "plist.h"
31 : #include "nexthop.h"
32 : #include "northbound_cli.h"
33 : #include "lib/route_types.h"
34 : #include "vrf.h"
35 : #include "frrstr.h"
36 :
37 : #include "zebra/zebra_router.h"
38 : #include "zebra/redistribute.h"
39 : #include "zebra/debug.h"
40 : #include "zebra/zebra_rnh.h"
41 : #include "zebra/zebra_routemap.h"
42 :
43 : #include "zebra/zebra_routemap_clippy.c"
44 :
45 : static uint32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER;
46 : static struct thread *zebra_t_rmap_update = NULL;
47 : char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
48 :
49 : struct nh_rmap_obj {
50 : struct nexthop *nexthop;
51 : vrf_id_t vrf_id;
52 : uint32_t source_protocol;
53 : uint8_t instance;
54 : int metric;
55 : route_tag_t tag;
56 : };
57 :
58 : static void zebra_route_map_set_delay_timer(uint32_t value);
59 :
60 : /* 'match tag TAG'
61 : * Match function return 1 if match is success else return 0
62 : */
63 : static enum route_map_cmd_result_t
64 0 : route_match_tag(void *rule, const struct prefix *prefix, void *object)
65 : {
66 0 : route_tag_t *tag;
67 0 : struct nh_rmap_obj *nh_data;
68 :
69 0 : tag = rule;
70 0 : nh_data = object;
71 :
72 0 : if (nh_data->tag == *tag)
73 0 : return RMAP_MATCH;
74 :
75 : return RMAP_NOMATCH;
76 : }
77 :
78 : /* Route map commands for tag matching */
79 : static const struct route_map_rule_cmd route_match_tag_cmd = {
80 : "tag",
81 : route_match_tag,
82 : route_map_rule_tag_compile,
83 : route_map_rule_tag_free,
84 : };
85 :
86 :
87 : /* `match interface IFNAME' */
88 : /* Match function return 1 if match is success else return zero. */
89 : static enum route_map_cmd_result_t
90 0 : route_match_interface(void *rule, const struct prefix *prefix, void *object)
91 : {
92 0 : struct nh_rmap_obj *nh_data;
93 0 : char *ifname = rule;
94 0 : ifindex_t ifindex;
95 :
96 0 : if (strcasecmp(ifname, "any") == 0)
97 : return RMAP_MATCH;
98 0 : nh_data = object;
99 0 : if (!nh_data || !nh_data->nexthop)
100 : return RMAP_NOMATCH;
101 0 : ifindex = ifname2ifindex(ifname, nh_data->vrf_id);
102 0 : if (ifindex == 0)
103 : return RMAP_NOMATCH;
104 0 : if (nh_data->nexthop->ifindex == ifindex)
105 : return RMAP_MATCH;
106 :
107 : return RMAP_NOMATCH;
108 : }
109 :
110 : /* Route map `match interface' match statement. `arg' is IFNAME value */
111 0 : static void *route_match_interface_compile(const char *arg)
112 : {
113 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
114 : }
115 :
116 : /* Free route map's compiled `match interface' value. */
117 0 : static void route_match_interface_free(void *rule)
118 : {
119 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
120 0 : }
121 :
122 0 : static void show_vrf_proto_rm(struct vty *vty, struct zebra_vrf *zvrf,
123 : int af_type)
124 : {
125 0 : int i;
126 :
127 0 : vty_out(vty, "Protocol : route-map\n");
128 0 : vty_out(vty, "-------------------------------------\n");
129 :
130 0 : for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
131 0 : if (PROTO_RM_NAME(zvrf, af_type, i))
132 0 : vty_out(vty, "%-24s : %-10s\n", zebra_route_string(i),
133 : PROTO_RM_NAME(zvrf, af_type, i));
134 : else
135 0 : vty_out(vty, "%-24s : none\n", zebra_route_string(i));
136 : }
137 :
138 0 : if (PROTO_RM_NAME(zvrf, af_type, i))
139 0 : vty_out(vty, "%-24s : %-10s\n", "any",
140 : PROTO_RM_NAME(zvrf, af_type, i));
141 : else
142 0 : vty_out(vty, "%-24s : none\n", "any");
143 0 : }
144 :
145 0 : static void show_vrf_nht_rm(struct vty *vty, struct zebra_vrf *zvrf,
146 : int af_type, json_object *json)
147 : {
148 0 : int i;
149 :
150 0 : if (!json) {
151 0 : vty_out(vty, "Protocol : route-map\n");
152 0 : vty_out(vty, "-------------------------------------\n");
153 : }
154 :
155 0 : for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
156 0 : if (json) {
157 0 : if (NHT_RM_NAME(zvrf, af_type, i))
158 0 : json_object_string_add(
159 : json, zebra_route_string(i),
160 : NHT_RM_NAME(zvrf, af_type, i));
161 : else
162 0 : json_object_string_add(
163 : json, zebra_route_string(i), "none");
164 : } else {
165 0 : if (NHT_RM_NAME(zvrf, af_type, i))
166 0 : vty_out(vty, "%-24s : %-10s\n",
167 : zebra_route_string(i),
168 : NHT_RM_NAME(zvrf, af_type, i));
169 : else
170 0 : vty_out(vty, "%-24s : none\n",
171 : zebra_route_string(i));
172 : }
173 : }
174 :
175 0 : if (json) {
176 0 : if (NHT_RM_NAME(zvrf, af_type, i))
177 0 : json_object_string_add(json, "any",
178 : NHT_RM_NAME(zvrf, af_type, i));
179 : else
180 0 : json_object_string_add(json, "any", "none");
181 : } else {
182 0 : if (NHT_RM_NAME(zvrf, af_type, i))
183 0 : vty_out(vty, "%-24s : %-10s\n", "any",
184 : NHT_RM_NAME(zvrf, af_type, i));
185 : else
186 0 : vty_out(vty, "%-24s : none\n", "any");
187 : }
188 0 : }
189 :
190 0 : static int show_proto_rm(struct vty *vty, int af_type, const char *vrf_all,
191 : const char *vrf_name)
192 : {
193 0 : struct zebra_vrf *zvrf;
194 :
195 0 : if (vrf_all) {
196 0 : struct vrf *vrf;
197 :
198 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
199 0 : zvrf = (struct zebra_vrf *)vrf->info;
200 0 : if (zvrf == NULL)
201 0 : continue;
202 0 : vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
203 0 : show_vrf_proto_rm(vty, zvrf, af_type);
204 : }
205 : } else {
206 0 : vrf_id_t vrf_id = VRF_DEFAULT;
207 :
208 0 : if (vrf_name)
209 0 : VRF_GET_ID(vrf_id, vrf_name, false);
210 :
211 0 : zvrf = zebra_vrf_lookup_by_id(vrf_id);
212 0 : if (!zvrf)
213 : return CMD_SUCCESS;
214 :
215 0 : vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
216 0 : show_vrf_proto_rm(vty, zvrf, af_type);
217 : }
218 :
219 : return CMD_SUCCESS;
220 : }
221 :
222 0 : static int show_nht_rm(struct vty *vty, int af_type, const char *vrf_all,
223 : const char *vrf_name, bool use_json)
224 : {
225 0 : struct zebra_vrf *zvrf;
226 0 : json_object *json = NULL;
227 0 : json_object *json_vrfs = NULL;
228 :
229 0 : if (use_json) {
230 0 : json = json_object_new_object();
231 0 : json_vrfs = json_object_new_object();
232 0 : json_object_string_add(json, "afi",
233 : (af_type == AFI_IP) ? "ipv4" : "ipv6");
234 : }
235 :
236 0 : if (vrf_all) {
237 0 : struct vrf *vrf;
238 :
239 0 : if (use_json)
240 0 : json_object_object_add(json, "vrfs", json_vrfs);
241 :
242 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
243 0 : zvrf = (struct zebra_vrf *)vrf->info;
244 0 : if (zvrf == NULL)
245 0 : continue;
246 :
247 0 : if (use_json) {
248 0 : json_object *json_proto = NULL;
249 0 : json_object *json_vrf = NULL;
250 0 : json_vrf = json_object_new_object();
251 0 : json_object_object_add(
252 0 : json_vrfs, zvrf->vrf->name, json_vrf);
253 0 : json_proto = json_object_new_object();
254 0 : json_object_object_add(json_vrf, "protocols",
255 : json_proto);
256 0 : show_vrf_nht_rm(vty, zvrf, af_type, json_proto);
257 : } else {
258 0 : vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
259 0 : show_vrf_nht_rm(vty, zvrf, af_type, NULL);
260 : }
261 : }
262 : } else {
263 0 : json_object *json_proto = NULL;
264 0 : json_object *json_vrf = NULL;
265 0 : vrf_id_t vrf_id = VRF_DEFAULT;
266 :
267 0 : if (vrf_name)
268 0 : VRF_GET_ID(vrf_id, vrf_name, false);
269 :
270 0 : zvrf = zebra_vrf_lookup_by_id(vrf_id);
271 0 : if (!zvrf) {
272 0 : json_object_free(json);
273 0 : json_object_free(json_vrfs);
274 0 : return CMD_SUCCESS;
275 : }
276 :
277 0 : if (use_json) {
278 0 : json_object_object_add(json, "vrfs", json_vrfs);
279 0 : json_vrf = json_object_new_object();
280 0 : json_object_object_add(json_vrfs, zvrf->vrf->name,
281 : json_vrf);
282 0 : json_proto = json_object_new_object();
283 0 : json_object_object_add(json_vrf, "protocols",
284 : json_proto);
285 0 : show_vrf_nht_rm(vty, zvrf, af_type, json_proto);
286 : } else {
287 0 : vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
288 0 : show_vrf_nht_rm(vty, zvrf, af_type, NULL);
289 : }
290 : }
291 :
292 0 : if (use_json)
293 0 : vty_json(vty, json);
294 :
295 : return CMD_SUCCESS;
296 : }
297 :
298 : /* Route map commands for interface matching */
299 : static const struct route_map_rule_cmd route_match_interface_cmd = {
300 : "interface",
301 : route_match_interface,
302 : route_match_interface_compile,
303 : route_match_interface_free
304 : };
305 :
306 0 : static int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap,
307 : int rtype, afi_t afi, safi_t safi)
308 : {
309 0 : struct route_table *table;
310 :
311 0 : if (PROTO_RM_NAME(zvrf, afi, rtype)) {
312 0 : if (strcmp(PROTO_RM_NAME(zvrf, afi, rtype), rmap) == 0)
313 : return CMD_SUCCESS;
314 :
315 0 : XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype));
316 : }
317 0 : route_map_counter_decrement(PROTO_RM_MAP(zvrf, afi, rtype));
318 0 : PROTO_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
319 0 : PROTO_RM_MAP(zvrf, afi, rtype) =
320 0 : route_map_lookup_by_name(PROTO_RM_NAME(zvrf, afi, rtype));
321 0 : route_map_counter_increment(PROTO_RM_MAP(zvrf, afi, rtype));
322 :
323 0 : if (PROTO_RM_MAP(zvrf, afi, rtype)) {
324 :
325 0 : if (IS_ZEBRA_DEBUG_RIB_DETAILED)
326 0 : zlog_debug(
327 : "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
328 : zvrf->vrf->vrf_id, rtype);
329 : /* Process routes of interested address-families. */
330 0 : table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id);
331 0 : if (table)
332 0 : rib_update_table(table, RIB_UPDATE_RMAP_CHANGE,
333 : rtype);
334 : }
335 :
336 : return CMD_SUCCESS;
337 : }
338 :
339 0 : static int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap,
340 : int rtype, afi_t afi, safi_t safi)
341 : {
342 0 : struct route_table *table;
343 :
344 0 : if (!PROTO_RM_NAME(zvrf, afi, rtype))
345 : return CMD_SUCCESS;
346 :
347 0 : if (!rmap || strcmp(rmap, PROTO_RM_NAME(zvrf, afi, rtype)) == 0) {
348 :
349 0 : route_map_counter_decrement(PROTO_RM_MAP(zvrf, afi, rtype));
350 0 : if (PROTO_RM_MAP(zvrf, afi, rtype)) {
351 0 : if (IS_ZEBRA_DEBUG_RIB_DETAILED)
352 0 : zlog_debug(
353 : "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
354 : zvrf->vrf->vrf_id, rtype);
355 0 : PROTO_RM_MAP(zvrf, afi, rtype) = NULL;
356 :
357 : /* Process routes of interested address-families. */
358 0 : table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id);
359 0 : if (table)
360 0 : rib_update_table(table, RIB_UPDATE_RMAP_CHANGE,
361 : rtype);
362 : }
363 0 : XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype));
364 : }
365 : return CMD_SUCCESS;
366 : }
367 :
368 0 : static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype,
369 : int afi)
370 : {
371 :
372 0 : if (NHT_RM_NAME(zvrf, afi, rtype)) {
373 0 : if (strcmp(NHT_RM_NAME(zvrf, afi, rtype), rmap) == 0)
374 : return CMD_SUCCESS;
375 :
376 0 : XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype));
377 : }
378 0 : route_map_counter_decrement(NHT_RM_MAP(zvrf, afi, rtype));
379 0 : NHT_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
380 0 : NHT_RM_MAP(zvrf, afi, rtype) =
381 0 : route_map_lookup_by_name(NHT_RM_NAME(zvrf, afi, rtype));
382 0 : route_map_counter_increment(NHT_RM_MAP(zvrf, afi, rtype));
383 :
384 0 : if (NHT_RM_MAP(zvrf, afi, rtype))
385 0 : zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST);
386 :
387 : return CMD_SUCCESS;
388 : }
389 :
390 0 : static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype,
391 : int afi)
392 : {
393 :
394 0 : if (!NHT_RM_NAME(zvrf, afi, rtype))
395 : return CMD_SUCCESS;
396 :
397 0 : if (!rmap || strcmp(rmap, NHT_RM_NAME(zvrf, afi, rtype)) == 0) {
398 0 : route_map_counter_decrement(NHT_RM_MAP(zvrf, afi, rtype));
399 0 : if (NHT_RM_MAP(zvrf, afi, rtype)) {
400 0 : if (IS_ZEBRA_DEBUG_RIB_DETAILED)
401 0 : zlog_debug(
402 : "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
403 : zvrf->vrf->vrf_id, rtype);
404 0 : NHT_RM_MAP(zvrf, afi, rtype) = NULL;
405 :
406 0 : zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST);
407 : }
408 0 : XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype));
409 : }
410 : return CMD_SUCCESS;
411 : }
412 :
413 0 : DEFPY_YANG(
414 : match_ip_address_prefix_len, match_ip_address_prefix_len_cmd,
415 : "match ip address prefix-len (0-32)$length",
416 : MATCH_STR
417 : IP_STR
418 : "Match prefix length of IP address\n"
419 : "Match prefix length of IP address\n"
420 : "Prefix length\n")
421 : {
422 0 : const char *xpath =
423 : "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
424 0 : char xpath_value[XPATH_MAXLEN];
425 :
426 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
427 0 : snprintf(
428 : xpath_value, sizeof(xpath_value),
429 : "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
430 : xpath);
431 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
432 :
433 0 : return nb_cli_apply_changes(vty, NULL);
434 : }
435 :
436 0 : DEFPY_YANG(
437 : no_match_ip_address_prefix_len, no_match_ip_address_prefix_len_cmd,
438 : "no match ip address prefix-len [(0-32)]",
439 : NO_STR
440 : MATCH_STR
441 : IP_STR
442 : "Match prefix length of IP address\n"
443 : "Match prefix length of IP address\n"
444 : "Prefix length\n")
445 : {
446 0 : const char *xpath =
447 : "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
448 :
449 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
450 :
451 0 : return nb_cli_apply_changes(vty, NULL);
452 : }
453 :
454 0 : DEFPY_YANG(
455 : match_ipv6_address_prefix_len, match_ipv6_address_prefix_len_cmd,
456 : "match ipv6 address prefix-len (0-128)$length",
457 : MATCH_STR
458 : IPV6_STR
459 : "Match prefix length of IPv6 address\n"
460 : "Match prefix length of IPv6 address\n"
461 : "Prefix length\n")
462 : {
463 0 : const char *xpath =
464 : "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
465 0 : char xpath_value[XPATH_MAXLEN];
466 :
467 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
468 0 : snprintf(
469 : xpath_value, sizeof(xpath_value),
470 : "%s/rmap-match-condition/frr-zebra-route-map:ipv6-prefix-length",
471 : xpath);
472 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
473 :
474 0 : return nb_cli_apply_changes(vty, NULL);
475 : }
476 :
477 0 : DEFPY_YANG(
478 : no_match_ipv6_address_prefix_len, no_match_ipv6_address_prefix_len_cmd,
479 : "no match ipv6 address prefix-len [(0-128)]",
480 : NO_STR
481 : MATCH_STR
482 : IPV6_STR
483 : "Match prefix length of IPv6 address\n"
484 : "Match prefix length of IPv6 address\n"
485 : "Prefix length\n")
486 : {
487 0 : const char *xpath =
488 : "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
489 :
490 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
491 :
492 0 : return nb_cli_apply_changes(vty, NULL);
493 : }
494 :
495 0 : DEFPY_YANG(
496 : match_ip_nexthop_prefix_len, match_ip_nexthop_prefix_len_cmd,
497 : "match ip next-hop prefix-len (0-32)$length",
498 : MATCH_STR
499 : IP_STR
500 : "Match prefixlen of nexthop IP address\n"
501 : "Match prefixlen of given nexthop\n"
502 : "Prefix length\n")
503 : {
504 0 : const char *xpath =
505 : "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
506 0 : char xpath_value[XPATH_MAXLEN];
507 :
508 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
509 0 : snprintf(
510 : xpath_value, sizeof(xpath_value),
511 : "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
512 : xpath);
513 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
514 :
515 0 : return nb_cli_apply_changes(vty, NULL);
516 : }
517 :
518 0 : DEFPY_YANG(
519 : no_match_ip_nexthop_prefix_len, no_match_ip_nexthop_prefix_len_cmd,
520 : "no match ip next-hop prefix-len [(0-32)]",
521 : NO_STR
522 : MATCH_STR
523 : IP_STR
524 : "Match prefixlen of nexthop IP address\n"
525 : "Match prefix length of nexthop\n"
526 : "Prefix length\n")
527 : {
528 0 : const char *xpath =
529 : "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
530 :
531 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
532 :
533 0 : return nb_cli_apply_changes(vty, NULL);
534 : }
535 :
536 0 : DEFPY_YANG(
537 : match_source_protocol, match_source_protocol_cmd,
538 : "match source-protocol " FRR_REDIST_STR_ZEBRA "$proto",
539 : MATCH_STR
540 : "Match protocol via which the route was learnt\n"
541 : FRR_REDIST_HELP_STR_ZEBRA)
542 : {
543 0 : const char *xpath =
544 : "./match-condition[condition='frr-zebra-route-map:source-protocol']";
545 0 : char xpath_value[XPATH_MAXLEN];
546 :
547 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
548 0 : snprintf(xpath_value, sizeof(xpath_value),
549 : "%s/rmap-match-condition/frr-zebra-route-map:source-protocol",
550 : xpath);
551 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, proto);
552 :
553 0 : return nb_cli_apply_changes(vty, NULL);
554 : }
555 :
556 0 : DEFPY_YANG(
557 : no_match_source_protocol, no_match_source_protocol_cmd,
558 : "no match source-protocol [" FRR_REDIST_STR_ZEBRA "]",
559 : NO_STR
560 : MATCH_STR
561 : "Match protocol via which the route was learnt\n"
562 : FRR_REDIST_HELP_STR_ZEBRA)
563 : {
564 0 : const char *xpath =
565 : "./match-condition[condition='frr-zebra-route-map:source-protocol']";
566 :
567 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
568 :
569 0 : return nb_cli_apply_changes(vty, NULL);
570 : }
571 :
572 0 : DEFPY_YANG(
573 : match_source_instance, match_source_instance_cmd,
574 : "match source-instance (0-255)$instance",
575 : MATCH_STR
576 : "Match the protocol's instance number\n"
577 : "The instance number\n")
578 : {
579 0 : const char *xpath =
580 : "./match-condition[condition='frr-zebra-route-map:source-instance']";
581 0 : char xpath_value[XPATH_MAXLEN];
582 :
583 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
584 0 : snprintf(xpath_value, sizeof(xpath_value),
585 : "%s/rmap-match-condition/frr-zebra-route-map:source-instance",
586 : xpath);
587 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, instance_str);
588 :
589 0 : return nb_cli_apply_changes(vty, NULL);
590 : }
591 :
592 0 : DEFPY_YANG(
593 : no_match_source_instance, no_match_source_instance_cmd,
594 : "no match source-instance [(0-255)]",
595 : NO_STR MATCH_STR
596 : "Match the protocol's instance number\n"
597 : "The instance number\n")
598 : {
599 0 : const char *xpath =
600 : "./match-condition[condition='frr-zebra-route-map:source-instance']";
601 :
602 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
603 :
604 0 : return nb_cli_apply_changes(vty, NULL);
605 : }
606 :
607 : /* set functions */
608 :
609 0 : DEFPY_YANG(
610 : set_src, set_src_cmd,
611 : "set src <A.B.C.D$addrv4|X:X::X:X$addrv6>",
612 : SET_STR
613 : "src address for route\n"
614 : "IPv4 src address\n"
615 : "IPv6 src address\n")
616 : {
617 0 : const char *xpath =
618 : "./set-action[action='frr-zebra-route-map:src-address']";
619 0 : char xpath_value[XPATH_MAXLEN];
620 :
621 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
622 0 : if (addrv4_str) {
623 0 : snprintf(
624 : xpath_value, sizeof(xpath_value),
625 : "%s/rmap-set-action/frr-zebra-route-map:ipv4-src-address",
626 : xpath);
627 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
628 : addrv4_str);
629 : } else {
630 0 : snprintf(
631 : xpath_value, sizeof(xpath_value),
632 : "%s/rmap-set-action/frr-zebra-route-map:ipv6-src-address",
633 : xpath);
634 0 : nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
635 : addrv6_str);
636 : }
637 :
638 0 : return nb_cli_apply_changes(vty, NULL);
639 : }
640 :
641 0 : DEFPY_YANG(
642 : no_set_src, no_set_src_cmd,
643 : "no set src [<A.B.C.D|X:X::X:X>]",
644 : NO_STR
645 : SET_STR
646 : "Source address for route\n"
647 : "IPv4 address\n"
648 : "IPv6 address\n")
649 : {
650 0 : const char *xpath =
651 : "./set-action[action='frr-zebra-route-map:src-address']";
652 :
653 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
654 :
655 0 : return nb_cli_apply_changes(vty, NULL);
656 : }
657 :
658 0 : DEFUN_YANG (zebra_route_map_timer,
659 : zebra_route_map_timer_cmd,
660 : "zebra route-map delay-timer (0-600)",
661 : ZEBRA_STR
662 : "Set route-map parameters\n"
663 : "Time to wait before route-map updates are processed\n"
664 : "0 means route-map changes are run immediately instead of delaying\n")
665 : {
666 0 : int idx_number = 3;
667 0 : uint32_t rmap_delay_timer;
668 :
669 0 : rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10);
670 0 : zebra_route_map_set_delay_timer(rmap_delay_timer);
671 :
672 0 : return (CMD_SUCCESS);
673 : }
674 :
675 0 : DEFUN_YANG (no_zebra_route_map_timer,
676 : no_zebra_route_map_timer_cmd,
677 : "no zebra route-map delay-timer [(0-600)]",
678 : NO_STR
679 : ZEBRA_STR
680 : "Set route-map parameters\n"
681 : "Reset delay-timer to default value, 30 secs\n"
682 : "0 means route-map changes are run immediately instead of delaying\n")
683 : {
684 0 : zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER);
685 :
686 0 : return (CMD_SUCCESS);
687 : }
688 :
689 0 : DEFPY_YANG (ip_protocol,
690 : ip_protocol_cmd,
691 : "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
692 : " $proto route-map ROUTE-MAP$rmap",
693 : IP_STR
694 : "Filter routing info exchanged between zebra and protocol\n"
695 : FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
696 : "Specify route-map\n"
697 : "Route map name\n")
698 : {
699 0 : int ret, rtype;
700 :
701 0 : assert(proto);
702 0 : assert(rmap);
703 :
704 0 : ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
705 :
706 0 : if (!zvrf)
707 : return CMD_WARNING;
708 :
709 0 : if (strcasecmp(proto, "any") == 0)
710 : rtype = ZEBRA_ROUTE_MAX;
711 : else
712 0 : rtype = proto_name2num(proto);
713 0 : if (rtype < 0) {
714 0 : vty_out(vty, "invalid protocol name \"%s\"\n", proto);
715 0 : return CMD_WARNING_CONFIG_FAILED;
716 : }
717 :
718 0 : ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
719 :
720 0 : return ret;
721 : }
722 :
723 0 : DEFPY_YANG (no_ip_protocol,
724 : no_ip_protocol_cmd,
725 : "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
726 : " $proto [route-map ROUTE-MAP$rmap]",
727 : NO_STR
728 : IP_STR
729 : "Stop filtering routing info between zebra and protocol\n"
730 : FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
731 : "Specify route-map\n"
732 : "Route map name\n")
733 : {
734 0 : int ret, rtype;
735 :
736 0 : assert(proto);
737 :
738 0 : ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
739 :
740 0 : if (!zvrf)
741 : return CMD_WARNING;
742 :
743 0 : if (strcasecmp(proto, "any") == 0)
744 : rtype = ZEBRA_ROUTE_MAX;
745 : else
746 0 : rtype = proto_name2num(proto);
747 0 : if (rtype < 0) {
748 0 : vty_out(vty, "invalid protocol name \"%s\"\n", proto);
749 0 : return CMD_WARNING_CONFIG_FAILED;
750 : }
751 :
752 0 : ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
753 :
754 0 : return ret;
755 : }
756 :
757 0 : DEFPY_YANG (show_ip_protocol,
758 : show_ip_protocol_cmd,
759 : "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
760 : SHOW_STR
761 : IP_STR
762 : "IP protocol filtering status\n"
763 : VRF_FULL_CMD_HELP_STR)
764 : {
765 0 : int ret = show_proto_rm(vty, AFI_IP, vrf_all, vrf_name);
766 :
767 0 : return ret;
768 : }
769 :
770 0 : DEFPY_YANG (ipv6_protocol,
771 : ipv6_protocol_cmd,
772 : "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
773 : " $proto route-map ROUTE-MAP$rmap",
774 : IP6_STR
775 : "Filter IPv6 routing info exchanged between zebra and protocol\n"
776 : FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
777 : "Specify route-map\n"
778 : "Route map name\n")
779 : {
780 0 : int ret, rtype;
781 :
782 0 : assert(rmap);
783 0 : assert(proto);
784 :
785 0 : ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
786 :
787 0 : if (!zvrf)
788 : return CMD_WARNING;
789 :
790 0 : if (strcasecmp(proto, "any") == 0)
791 : rtype = ZEBRA_ROUTE_MAX;
792 : else
793 0 : rtype = proto_name2num(proto);
794 0 : if (rtype < 0) {
795 0 : vty_out(vty, "invalid protocol name \"%s\"\n", proto);
796 0 : return CMD_WARNING_CONFIG_FAILED;
797 : }
798 :
799 0 : ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
800 :
801 0 : return ret;
802 : }
803 :
804 0 : DEFPY_YANG (no_ipv6_protocol,
805 : no_ipv6_protocol_cmd,
806 : "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
807 : " $proto [route-map ROUTE-MAP$rmap]",
808 : NO_STR
809 : IP6_STR
810 : "Stop filtering IPv6 routing info between zebra and protocol\n"
811 : FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
812 : "Specify route-map\n"
813 : "Route map name\n")
814 : {
815 0 : int ret, rtype;
816 :
817 0 : assert(proto);
818 :
819 0 : ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
820 :
821 0 : if (!zvrf)
822 : return CMD_WARNING;
823 :
824 0 : if (strcasecmp(proto, "any") == 0)
825 : rtype = ZEBRA_ROUTE_MAX;
826 : else
827 0 : rtype = proto_name2num(proto);
828 0 : if (rtype < 0) {
829 0 : vty_out(vty, "invalid protocol name \"%s\"\n", proto);
830 0 : return CMD_WARNING_CONFIG_FAILED;
831 : }
832 :
833 0 : ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
834 :
835 0 : return ret;
836 : }
837 :
838 0 : DEFPY_YANG (show_ipv6_protocol,
839 : show_ipv6_protocol_cmd,
840 : "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
841 : SHOW_STR
842 : IP6_STR
843 : "IPv6 protocol filtering status\n"
844 : VRF_FULL_CMD_HELP_STR)
845 : {
846 0 : int ret = show_proto_rm(vty, AFI_IP6, vrf_all, vrf_name);
847 :
848 0 : return ret;
849 : }
850 :
851 0 : DEFPY_YANG (ip_protocol_nht_rmap,
852 : ip_protocol_nht_rmap_cmd,
853 : "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
854 : " $proto route-map ROUTE-MAP$rmap",
855 : IP_STR
856 : "Filter Next Hop tracking route resolution\n"
857 : FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
858 : "Specify route map\n"
859 : "Route map name\n")
860 : {
861 :
862 0 : int ret, rtype;
863 :
864 0 : assert(proto);
865 0 : assert(rmap);
866 :
867 0 : ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
868 :
869 0 : if (!zvrf)
870 : return CMD_WARNING;
871 :
872 0 : if (strcasecmp(proto, "any") == 0)
873 : rtype = ZEBRA_ROUTE_MAX;
874 : else
875 0 : rtype = proto_name2num(proto);
876 0 : if (rtype < 0) {
877 0 : vty_out(vty, "invalid protocol name \"%s\"\n", proto);
878 0 : return CMD_WARNING_CONFIG_FAILED;
879 : }
880 :
881 0 : ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP);
882 :
883 0 : return ret;
884 : }
885 :
886 0 : DEFPY_YANG (no_ip_protocol_nht_rmap,
887 : no_ip_protocol_nht_rmap_cmd,
888 : "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
889 : " $proto route-map [ROUTE-MAP$rmap]",
890 : NO_STR
891 : IP_STR
892 : "Filter Next Hop tracking route resolution\n"
893 : FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
894 : "Specify route map\n"
895 : "Route map name\n")
896 : {
897 0 : int ret, rtype;
898 :
899 0 : assert(proto);
900 :
901 0 : ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
902 :
903 0 : if (!zvrf)
904 : return CMD_WARNING;
905 :
906 0 : if (strcasecmp(proto, "any") == 0)
907 : rtype = ZEBRA_ROUTE_MAX;
908 : else
909 0 : rtype = proto_name2num(proto);
910 0 : if (rtype < 0) {
911 0 : vty_out(vty, "invalid protocol name \"%s\"\n", proto);
912 0 : return CMD_WARNING_CONFIG_FAILED;
913 : }
914 :
915 0 : ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP);
916 :
917 0 : return ret;
918 : }
919 :
920 0 : DEFPY_YANG (show_ip_protocol_nht,
921 : show_ip_protocol_nht_cmd,
922 : "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
923 : SHOW_STR
924 : IP_STR
925 : "IPv4 nexthop tracking table\n"
926 : "IPv4 Next Hop tracking filtering status\n"
927 : VRF_CMD_HELP_STR
928 : "All VRFs\n"
929 : JSON_STR)
930 : {
931 0 : int ret;
932 0 : bool uj = use_json(argc, argv);
933 :
934 0 : ret = show_nht_rm(vty, AFI_IP, vrf_all, vrf_name, uj);
935 :
936 0 : return ret;
937 : }
938 :
939 0 : DEFPY_YANG (ipv6_protocol_nht_rmap,
940 : ipv6_protocol_nht_rmap_cmd,
941 : "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
942 : " $proto route-map ROUTE-MAP$rmap",
943 : IP6_STR
944 : "Filter Next Hop tracking route resolution\n"
945 : FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
946 : "Specify route map\n"
947 : "Route map name\n")
948 : {
949 0 : int ret, rtype;
950 :
951 0 : assert(rmap);
952 0 : assert(proto);
953 :
954 0 : ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
955 :
956 0 : if (!zvrf)
957 : return CMD_WARNING;
958 :
959 0 : if (strcasecmp(proto, "any") == 0)
960 : rtype = ZEBRA_ROUTE_MAX;
961 : else
962 0 : rtype = proto_name2num(proto);
963 0 : if (rtype < 0) {
964 0 : vty_out(vty, "invalid protocol name \"%s\"\n", proto);
965 0 : return CMD_WARNING_CONFIG_FAILED;
966 : }
967 :
968 0 : ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP6);
969 :
970 0 : return ret;
971 : }
972 :
973 0 : DEFPY_YANG (no_ipv6_protocol_nht_rmap,
974 : no_ipv6_protocol_nht_rmap_cmd,
975 : "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
976 : " $proto [route-map ROUTE-MAP$rmap]",
977 : NO_STR
978 : IP6_STR
979 : "Filter Next Hop tracking route resolution\n"
980 : FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
981 : "Specify route map\n"
982 : "Route map name\n")
983 : {
984 0 : int ret, rtype;
985 :
986 0 : assert(proto);
987 :
988 0 : ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
989 :
990 0 : if (!zvrf)
991 : return CMD_WARNING;
992 :
993 0 : if (strcasecmp(proto, "any") == 0)
994 : rtype = ZEBRA_ROUTE_MAX;
995 : else
996 0 : rtype = proto_name2num(proto);
997 0 : if (rtype < 0) {
998 0 : vty_out(vty, "invalid protocol name \"%s\"\n", proto);
999 0 : return CMD_WARNING_CONFIG_FAILED;
1000 : }
1001 :
1002 0 : ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP6);
1003 :
1004 0 : return ret;
1005 : }
1006 :
1007 0 : DEFPY_YANG (show_ipv6_protocol_nht,
1008 : show_ipv6_protocol_nht_cmd,
1009 : "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
1010 : SHOW_STR
1011 : IP6_STR
1012 : "IPv6 nexthop tracking table\n"
1013 : "IPv6 Next Hop tracking filtering status\n"
1014 : VRF_CMD_HELP_STR
1015 : "All VRFs\n"
1016 : JSON_STR)
1017 : {
1018 0 : int ret;
1019 0 : bool uj = use_json(argc, argv);
1020 :
1021 0 : ret = show_nht_rm(vty, AFI_IP6, vrf_all, vrf_name, uj);
1022 :
1023 0 : return ret;
1024 : }
1025 :
1026 : /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1027 :
1028 : /* `match ip next-hop IP_ACCESS_LIST' */
1029 :
1030 : /* Match function return 1 if match is success else return zero. */
1031 : static enum route_map_cmd_result_t
1032 0 : route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
1033 : {
1034 0 : struct access_list *alist;
1035 0 : struct nh_rmap_obj *nh_data;
1036 0 : struct prefix_ipv4 p;
1037 :
1038 0 : nh_data = object;
1039 0 : if (!nh_data)
1040 : return RMAP_NOMATCH;
1041 :
1042 0 : switch (nh_data->nexthop->type) {
1043 : case NEXTHOP_TYPE_IFINDEX:
1044 : /* Interface routes can't match ip next-hop */
1045 : return RMAP_NOMATCH;
1046 0 : case NEXTHOP_TYPE_IPV4_IFINDEX:
1047 : case NEXTHOP_TYPE_IPV4:
1048 0 : p.family = AF_INET;
1049 0 : p.prefix = nh_data->nexthop->gate.ipv4;
1050 0 : p.prefixlen = IPV4_MAX_BITLEN;
1051 0 : break;
1052 : case NEXTHOP_TYPE_IPV6:
1053 : case NEXTHOP_TYPE_IPV6_IFINDEX:
1054 : case NEXTHOP_TYPE_BLACKHOLE:
1055 : return RMAP_NOMATCH;
1056 : }
1057 0 : alist = access_list_lookup(AFI_IP, (char *)rule);
1058 0 : if (alist == NULL)
1059 : return RMAP_NOMATCH;
1060 :
1061 0 : return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
1062 0 : : RMAP_MATCH);
1063 : }
1064 :
1065 : /* Route map `ip next-hop' match statement. `arg' should be
1066 : access-list name. */
1067 0 : static void *route_match_ip_next_hop_compile(const char *arg)
1068 : {
1069 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1070 : }
1071 :
1072 : /* Free route map's compiled `. */
1073 0 : static void route_match_ip_next_hop_free(void *rule)
1074 : {
1075 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1076 0 : }
1077 :
1078 : /* Route map commands for ip next-hop matching. */
1079 : static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
1080 : "ip next-hop",
1081 : route_match_ip_next_hop,
1082 : route_match_ip_next_hop_compile,
1083 : route_match_ip_next_hop_free
1084 : };
1085 :
1086 : /* `match ip next-hop prefix-list PREFIX_LIST' */
1087 :
1088 : static enum route_map_cmd_result_t
1089 0 : route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
1090 : void *object)
1091 : {
1092 0 : struct prefix_list *plist;
1093 0 : struct nh_rmap_obj *nh_data;
1094 0 : struct prefix_ipv4 p;
1095 :
1096 0 : nh_data = (struct nh_rmap_obj *)object;
1097 0 : if (!nh_data)
1098 : return RMAP_NOMATCH;
1099 :
1100 0 : switch (nh_data->nexthop->type) {
1101 : case NEXTHOP_TYPE_IFINDEX:
1102 : /* Interface routes can't match ip next-hop */
1103 : return RMAP_NOMATCH;
1104 0 : case NEXTHOP_TYPE_IPV4_IFINDEX:
1105 : case NEXTHOP_TYPE_IPV4:
1106 0 : p.family = AF_INET;
1107 0 : p.prefix = nh_data->nexthop->gate.ipv4;
1108 0 : p.prefixlen = IPV4_MAX_BITLEN;
1109 0 : break;
1110 : case NEXTHOP_TYPE_IPV6:
1111 : case NEXTHOP_TYPE_IPV6_IFINDEX:
1112 : case NEXTHOP_TYPE_BLACKHOLE:
1113 : return RMAP_NOMATCH;
1114 : }
1115 0 : plist = prefix_list_lookup(AFI_IP, (char *)rule);
1116 0 : if (plist == NULL)
1117 : return RMAP_NOMATCH;
1118 :
1119 0 : return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH
1120 0 : : RMAP_MATCH);
1121 : }
1122 :
1123 0 : static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
1124 : {
1125 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1126 : }
1127 :
1128 0 : static void route_match_ip_next_hop_prefix_list_free(void *rule)
1129 : {
1130 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1131 0 : }
1132 :
1133 : static const struct route_map_rule_cmd
1134 : route_match_ip_next_hop_prefix_list_cmd = {
1135 : "ip next-hop prefix-list",
1136 : route_match_ip_next_hop_prefix_list,
1137 : route_match_ip_next_hop_prefix_list_compile,
1138 : route_match_ip_next_hop_prefix_list_free
1139 : };
1140 :
1141 : /* `match ip address IP_ACCESS_LIST' */
1142 :
1143 : /* Match function should return 1 if match is success else return
1144 : zero. */
1145 : static enum route_map_cmd_result_t
1146 0 : route_match_address(afi_t afi, void *rule, const struct prefix *prefix,
1147 : void *object)
1148 : {
1149 0 : struct access_list *alist;
1150 :
1151 0 : alist = access_list_lookup(afi, (char *)rule);
1152 0 : if (alist == NULL)
1153 : return RMAP_NOMATCH;
1154 :
1155 0 : return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH
1156 0 : : RMAP_MATCH);
1157 : }
1158 :
1159 : static enum route_map_cmd_result_t
1160 0 : route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
1161 : {
1162 0 : return route_match_address(AFI_IP, rule, prefix, object);
1163 : }
1164 :
1165 : static enum route_map_cmd_result_t
1166 0 : route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
1167 : {
1168 0 : return route_match_address(AFI_IP6, rule, prefix, object);
1169 : }
1170 :
1171 : /* Route map `ip address' match statement. `arg' should be
1172 : access-list name. */
1173 0 : static void *route_match_address_compile(const char *arg)
1174 : {
1175 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1176 : }
1177 :
1178 : /* Free route map's compiled `ip address' value. */
1179 0 : static void route_match_address_free(void *rule)
1180 : {
1181 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1182 0 : }
1183 :
1184 : /* Route map commands for ip address matching. */
1185 : static const struct route_map_rule_cmd route_match_ip_address_cmd = {
1186 : "ip address",
1187 : route_match_ip_address,
1188 : route_match_address_compile,
1189 : route_match_address_free
1190 : };
1191 :
1192 : /* Route map commands for ipv6 address matching. */
1193 : static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
1194 : "ipv6 address",
1195 : route_match_ipv6_address,
1196 : route_match_address_compile,
1197 : route_match_address_free
1198 : };
1199 :
1200 : /* `match ip address prefix-list PREFIX_LIST' */
1201 :
1202 : static enum route_map_cmd_result_t
1203 0 : route_match_address_prefix_list(void *rule, const struct prefix *prefix,
1204 : void *object, afi_t afi)
1205 : {
1206 0 : struct prefix_list *plist;
1207 :
1208 0 : plist = prefix_list_lookup(afi, (char *)rule);
1209 0 : if (plist == NULL)
1210 : return RMAP_NOMATCH;
1211 :
1212 0 : return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
1213 0 : : RMAP_MATCH);
1214 : }
1215 :
1216 : static enum route_map_cmd_result_t
1217 0 : route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
1218 : void *object)
1219 : {
1220 0 : return (route_match_address_prefix_list(rule, prefix, object, AFI_IP));
1221 : }
1222 :
1223 0 : static void *route_match_address_prefix_list_compile(const char *arg)
1224 : {
1225 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1226 : }
1227 :
1228 0 : static void route_match_address_prefix_list_free(void *rule)
1229 : {
1230 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1231 0 : }
1232 :
1233 : static const struct route_map_rule_cmd
1234 : route_match_ip_address_prefix_list_cmd = {
1235 : "ip address prefix-list",
1236 : route_match_ip_address_prefix_list,
1237 : route_match_address_prefix_list_compile,
1238 : route_match_address_prefix_list_free
1239 : };
1240 :
1241 : static enum route_map_cmd_result_t
1242 0 : route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
1243 : void *object)
1244 : {
1245 0 : return (route_match_address_prefix_list(rule, prefix, object, AFI_IP6));
1246 : }
1247 :
1248 : static const struct route_map_rule_cmd
1249 : route_match_ipv6_address_prefix_list_cmd = {
1250 : "ipv6 address prefix-list",
1251 : route_match_ipv6_address_prefix_list,
1252 : route_match_address_prefix_list_compile,
1253 : route_match_address_prefix_list_free
1254 : };
1255 :
1256 : /* `match ipv6 next-hop type <TYPE>' */
1257 :
1258 : static enum route_map_cmd_result_t
1259 0 : route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
1260 : void *object)
1261 : {
1262 0 : struct nh_rmap_obj *nh_data;
1263 :
1264 0 : if (prefix->family == AF_INET6) {
1265 0 : nh_data = (struct nh_rmap_obj *)object;
1266 0 : if (!nh_data)
1267 : return RMAP_NOMATCH;
1268 :
1269 0 : if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
1270 0 : return RMAP_MATCH;
1271 : }
1272 :
1273 : return RMAP_NOMATCH;
1274 : }
1275 :
1276 0 : static void *route_match_ipv6_next_hop_type_compile(const char *arg)
1277 : {
1278 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1279 : }
1280 :
1281 0 : static void route_match_ipv6_next_hop_type_free(void *rule)
1282 : {
1283 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1284 0 : }
1285 :
1286 : static const struct route_map_rule_cmd
1287 : route_match_ipv6_next_hop_type_cmd = {
1288 : "ipv6 next-hop type",
1289 : route_match_ipv6_next_hop_type,
1290 : route_match_ipv6_next_hop_type_compile,
1291 : route_match_ipv6_next_hop_type_free
1292 : };
1293 :
1294 : /* `match ip address prefix-len PREFIXLEN' */
1295 :
1296 : static enum route_map_cmd_result_t
1297 0 : route_match_address_prefix_len(void *rule, const struct prefix *prefix,
1298 : void *object)
1299 : {
1300 0 : uint32_t *prefixlen = (uint32_t *)rule;
1301 :
1302 0 : return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1303 : }
1304 :
1305 0 : static void *route_match_address_prefix_len_compile(const char *arg)
1306 : {
1307 0 : uint32_t *prefix_len;
1308 0 : char *endptr = NULL;
1309 0 : unsigned long tmpval;
1310 :
1311 : /* prefix len value shoud be integer. */
1312 0 : if (!all_digit(arg))
1313 : return NULL;
1314 :
1315 0 : errno = 0;
1316 0 : tmpval = strtoul(arg, &endptr, 10);
1317 0 : if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1318 : return NULL;
1319 :
1320 0 : prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1321 :
1322 0 : *prefix_len = tmpval;
1323 0 : return prefix_len;
1324 : }
1325 :
1326 0 : static void route_match_address_prefix_len_free(void *rule)
1327 : {
1328 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1329 0 : }
1330 :
1331 : static const struct route_map_rule_cmd
1332 : route_match_ip_address_prefix_len_cmd = {
1333 : "ip address prefix-len",
1334 : route_match_address_prefix_len,
1335 : route_match_address_prefix_len_compile,
1336 : route_match_address_prefix_len_free
1337 : };
1338 :
1339 : static const struct route_map_rule_cmd
1340 : route_match_ipv6_address_prefix_len_cmd = {
1341 : "ipv6 address prefix-len",
1342 : route_match_address_prefix_len,
1343 : route_match_address_prefix_len_compile,
1344 : route_match_address_prefix_len_free
1345 : };
1346 :
1347 : /* `match ip nexthop prefix-len PREFIXLEN' */
1348 :
1349 : static enum route_map_cmd_result_t
1350 0 : route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
1351 : void *object)
1352 : {
1353 0 : uint32_t *prefixlen = (uint32_t *)rule;
1354 0 : struct nh_rmap_obj *nh_data;
1355 0 : struct prefix_ipv4 p;
1356 :
1357 0 : nh_data = (struct nh_rmap_obj *)object;
1358 0 : if (!nh_data || !nh_data->nexthop)
1359 : return RMAP_NOMATCH;
1360 :
1361 0 : switch (nh_data->nexthop->type) {
1362 : case NEXTHOP_TYPE_IFINDEX:
1363 : /* Interface routes can't match ip next-hop */
1364 : return RMAP_NOMATCH;
1365 : case NEXTHOP_TYPE_IPV4_IFINDEX:
1366 : case NEXTHOP_TYPE_IPV4:
1367 : p.family = AF_INET;
1368 : p.prefix = nh_data->nexthop->gate.ipv4;
1369 0 : p.prefixlen = IPV4_MAX_BITLEN;
1370 : break;
1371 : case NEXTHOP_TYPE_IPV6:
1372 : case NEXTHOP_TYPE_IPV6_IFINDEX:
1373 : case NEXTHOP_TYPE_BLACKHOLE:
1374 : return RMAP_NOMATCH;
1375 : }
1376 0 : return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
1377 : }
1378 :
1379 : static const struct route_map_rule_cmd
1380 : route_match_ip_nexthop_prefix_len_cmd = {
1381 : "ip next-hop prefix-len",
1382 : route_match_ip_nexthop_prefix_len,
1383 : route_match_address_prefix_len_compile, /* reuse */
1384 : route_match_address_prefix_len_free /* reuse */
1385 : };
1386 :
1387 : /* `match ip next-hop type <blackhole>' */
1388 :
1389 : static enum route_map_cmd_result_t
1390 0 : route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
1391 : void *object)
1392 : {
1393 0 : struct nh_rmap_obj *nh_data;
1394 :
1395 0 : if (prefix->family == AF_INET) {
1396 0 : nh_data = (struct nh_rmap_obj *)object;
1397 0 : if (!nh_data)
1398 : return RMAP_NOMATCH;
1399 :
1400 0 : if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
1401 0 : return RMAP_MATCH;
1402 : }
1403 :
1404 : return RMAP_NOMATCH;
1405 : }
1406 :
1407 0 : static void *route_match_ip_next_hop_type_compile(const char *arg)
1408 : {
1409 0 : return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1410 : }
1411 :
1412 0 : static void route_match_ip_next_hop_type_free(void *rule)
1413 : {
1414 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1415 0 : }
1416 :
1417 : static const struct route_map_rule_cmd
1418 : route_match_ip_next_hop_type_cmd = {
1419 : "ip next-hop type",
1420 : route_match_ip_next_hop_type,
1421 : route_match_ip_next_hop_type_compile,
1422 : route_match_ip_next_hop_type_free
1423 : };
1424 :
1425 : /* `match source-protocol PROTOCOL' */
1426 :
1427 : static enum route_map_cmd_result_t
1428 0 : route_match_source_protocol(void *rule, const struct prefix *p, void *object)
1429 : {
1430 0 : uint32_t *rib_type = (uint32_t *)rule;
1431 0 : struct nh_rmap_obj *nh_data;
1432 :
1433 0 : nh_data = (struct nh_rmap_obj *)object;
1434 0 : if (!nh_data)
1435 : return RMAP_NOMATCH;
1436 :
1437 0 : return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
1438 0 : : RMAP_NOMATCH);
1439 : }
1440 :
1441 0 : static void *route_match_source_protocol_compile(const char *arg)
1442 : {
1443 0 : uint32_t *rib_type;
1444 0 : int i;
1445 :
1446 0 : i = proto_name2num(arg);
1447 0 : rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1448 :
1449 0 : *rib_type = i;
1450 :
1451 0 : return rib_type;
1452 : }
1453 :
1454 0 : static void route_match_source_protocol_free(void *rule)
1455 : {
1456 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1457 0 : }
1458 :
1459 : static const struct route_map_rule_cmd route_match_source_protocol_cmd = {
1460 : "source-protocol",
1461 : route_match_source_protocol,
1462 : route_match_source_protocol_compile,
1463 : route_match_source_protocol_free
1464 : };
1465 :
1466 : /* `source-instance` */
1467 : static enum route_map_cmd_result_t
1468 0 : route_match_source_instance(void *rule, const struct prefix *p, void *object)
1469 : {
1470 0 : uint8_t *instance = (uint8_t *)rule;
1471 0 : struct nh_rmap_obj *nh_data;
1472 :
1473 0 : nh_data = (struct nh_rmap_obj *)object;
1474 0 : if (!nh_data)
1475 : return RMAP_NOMATCH;
1476 :
1477 0 : return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
1478 : }
1479 :
1480 0 : static void *route_match_source_instance_compile(const char *arg)
1481 : {
1482 0 : uint8_t *instance;
1483 0 : int i;
1484 :
1485 0 : i = atoi(arg);
1486 0 : instance = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
1487 :
1488 0 : *instance = i;
1489 :
1490 0 : return instance;
1491 : }
1492 :
1493 0 : static void route_match_source_instance_free(void *rule)
1494 : {
1495 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1496 0 : }
1497 :
1498 : static const struct route_map_rule_cmd route_match_source_instance_cmd = {
1499 : "source-instance",
1500 : route_match_source_instance,
1501 : route_match_source_instance_compile,
1502 : route_match_source_instance_free
1503 : };
1504 :
1505 : /* `set src A.B.C.D' */
1506 :
1507 : /* Set src. */
1508 : static enum route_map_cmd_result_t
1509 0 : route_set_src(void *rule, const struct prefix *prefix, void *object)
1510 : {
1511 0 : struct nh_rmap_obj *nh_data;
1512 :
1513 0 : nh_data = (struct nh_rmap_obj *)object;
1514 0 : nh_data->nexthop->rmap_src = *(union g_addr *)rule;
1515 :
1516 0 : return RMAP_OKAY;
1517 : }
1518 :
1519 : /* set src compilation. */
1520 0 : static void *route_set_src_compile(const char *arg)
1521 : {
1522 0 : union g_addr src, *psrc;
1523 :
1524 0 : if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1)
1525 0 : || (inet_pton(AF_INET, arg, &src.ipv4) == 1)) {
1526 0 : psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr));
1527 0 : *psrc = src;
1528 0 : return psrc;
1529 : }
1530 : return NULL;
1531 : }
1532 :
1533 : /* Free route map's compiled `set src' value. */
1534 0 : static void route_set_src_free(void *rule)
1535 : {
1536 0 : XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1537 0 : }
1538 :
1539 : /* Set src rule structure. */
1540 : static const struct route_map_rule_cmd route_set_src_cmd = {
1541 : "src",
1542 : route_set_src,
1543 : route_set_src_compile,
1544 : route_set_src_free,
1545 : };
1546 :
1547 : /* The function checks if the changed routemap specified by parameter rmap
1548 : * matches the configured protocol routemaps in proto_rm table. If there is
1549 : * a match then rib_update_table() to process the routes.
1550 : */
1551 0 : static void zebra_rib_table_rm_update(const char *rmap)
1552 : {
1553 0 : int i = 0;
1554 0 : struct route_table *table;
1555 0 : struct vrf *vrf = NULL;
1556 0 : struct zebra_vrf *zvrf = NULL;
1557 0 : char *rmap_name;
1558 0 : struct route_map *old = NULL;
1559 :
1560 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1561 0 : zvrf = vrf->info;
1562 0 : if (!zvrf)
1563 0 : continue;
1564 0 : for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
1565 0 : rmap_name = PROTO_RM_NAME(zvrf, AFI_IP, i);
1566 0 : if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1567 0 : if (IS_ZEBRA_DEBUG_EVENT)
1568 0 : zlog_debug(
1569 : "%s : AFI_IP rmap %s, route type %s",
1570 : __func__, rmap,
1571 : zebra_route_string(i));
1572 :
1573 0 : old = PROTO_RM_MAP(zvrf, AFI_IP, i);
1574 :
1575 0 : PROTO_RM_MAP(zvrf, AFI_IP, i) =
1576 0 : route_map_lookup_by_name(rmap_name);
1577 : /* old is NULL. i.e Route map creation event.
1578 : * So update applied_counter.
1579 : * If Old is not NULL, i.e It may be routemap
1580 : * updation or deletion.
1581 : * So no need to update the counter.
1582 : */
1583 0 : if (!old)
1584 0 : route_map_counter_increment(
1585 : PROTO_RM_MAP(zvrf, AFI_IP, i));
1586 : /* There is single rib table for all protocols
1587 : */
1588 0 : table = zvrf->table[AFI_IP][SAFI_UNICAST];
1589 0 : if (table) {
1590 0 : rib_update_table(
1591 : table,
1592 : RIB_UPDATE_RMAP_CHANGE,
1593 : i);
1594 : }
1595 : }
1596 0 : rmap_name = PROTO_RM_NAME(zvrf, AFI_IP6, i);
1597 0 : if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1598 0 : if (IS_ZEBRA_DEBUG_EVENT)
1599 0 : zlog_debug(
1600 : "%s : AFI_IP6 rmap %s, route type %s",
1601 : __func__, rmap,
1602 : zebra_route_string(i));
1603 :
1604 0 : old = PROTO_RM_MAP(zvrf, AFI_IP6, i);
1605 :
1606 0 : PROTO_RM_MAP(zvrf, AFI_IP6, i) =
1607 0 : route_map_lookup_by_name(rmap_name);
1608 0 : if (!old)
1609 0 : route_map_counter_increment(
1610 : PROTO_RM_MAP(zvrf, AFI_IP6, i));
1611 : /* There is single rib table for all protocols
1612 : */
1613 0 : table = zvrf->table[AFI_IP6][SAFI_UNICAST];
1614 0 : if (table) {
1615 0 : rib_update_table(
1616 : table,
1617 : RIB_UPDATE_RMAP_CHANGE,
1618 : i);
1619 : }
1620 : }
1621 : }
1622 : }
1623 0 : }
1624 :
1625 : /* The function checks if the changed routemap specified by parameter rmap
1626 : * matches the configured protocol routemaps in nht_rm table. If there is
1627 : * a match then zebra_evaluate_rnh() to process the nexthops.
1628 : */
1629 0 : static void zebra_nht_rm_update(const char *rmap)
1630 : {
1631 0 : int i = 0;
1632 0 : struct route_table *table;
1633 0 : struct vrf *vrf = NULL;
1634 0 : struct zebra_vrf *zvrf = NULL;
1635 0 : char *rmap_name;
1636 0 : char afi_ip = 0;
1637 0 : char afi_ipv6 = 0;
1638 0 : struct route_map *old = NULL;
1639 :
1640 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1641 0 : zvrf = vrf->info;
1642 0 : if (!zvrf)
1643 0 : continue;
1644 0 : for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
1645 0 : rmap_name = NHT_RM_NAME(zvrf, AFI_IP, i);
1646 0 : if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1647 0 : if (IS_ZEBRA_DEBUG_EVENT)
1648 0 : zlog_debug(
1649 : "%s : AFI_IP rmap %s, route type %s",
1650 : __func__, rmap,
1651 : zebra_route_string(i));
1652 :
1653 0 : old = NHT_RM_MAP(zvrf, AFI_IP, i);
1654 :
1655 0 : NHT_RM_MAP(zvrf, AFI_IP, i) =
1656 0 : route_map_lookup_by_name(rmap_name);
1657 0 : if (!old)
1658 0 : route_map_counter_increment(
1659 : NHT_RM_MAP(zvrf, AFI_IP, i));
1660 : /* There is single rib table for all protocols
1661 : */
1662 0 : if (afi_ip == 0) {
1663 0 : table = zvrf->table[AFI_IP]
1664 : [SAFI_UNICAST];
1665 0 : if (table) {
1666 :
1667 0 : afi_ip = 1;
1668 :
1669 0 : zebra_evaluate_rnh(
1670 : zvrf, AFI_IP, 1, NULL,
1671 : SAFI_UNICAST);
1672 : }
1673 : }
1674 : }
1675 :
1676 0 : rmap_name = NHT_RM_NAME(zvrf, AFI_IP6, i);
1677 0 : if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
1678 0 : if (IS_ZEBRA_DEBUG_EVENT)
1679 0 : zlog_debug(
1680 : "%s : AFI_IP6 rmap %s, route type %s",
1681 : __func__, rmap,
1682 : zebra_route_string(i));
1683 :
1684 0 : old = NHT_RM_MAP(zvrf, AFI_IP6, i);
1685 :
1686 0 : NHT_RM_MAP(zvrf, AFI_IP6, i) =
1687 0 : route_map_lookup_by_name(rmap_name);
1688 0 : if (!old)
1689 0 : route_map_counter_increment(
1690 : NHT_RM_MAP(zvrf, AFI_IP6, i));
1691 : /* There is single rib table for all protocols
1692 : */
1693 0 : if (afi_ipv6 == 0) {
1694 0 : table = zvrf->table[AFI_IP6]
1695 : [SAFI_UNICAST];
1696 0 : if (table) {
1697 :
1698 0 : afi_ipv6 = 1;
1699 :
1700 0 : zebra_evaluate_rnh(
1701 : zvrf, AFI_IP, 1, NULL,
1702 : SAFI_UNICAST);
1703 : }
1704 : }
1705 : }
1706 : }
1707 : }
1708 0 : }
1709 :
1710 0 : static void zebra_route_map_process_update_cb(char *rmap_name)
1711 : {
1712 0 : if (IS_ZEBRA_DEBUG_EVENT)
1713 0 : zlog_debug("Event handler for route-map: %s",
1714 : rmap_name);
1715 0 : zebra_import_table_rm_update(rmap_name);
1716 0 : zebra_rib_table_rm_update(rmap_name);
1717 0 : zebra_nht_rm_update(rmap_name);
1718 0 : }
1719 :
1720 0 : static void zebra_route_map_update_timer(struct thread *thread)
1721 : {
1722 0 : if (IS_ZEBRA_DEBUG_EVENT)
1723 0 : zlog_debug("Event driven route-map update triggered");
1724 :
1725 0 : if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1726 0 : zlog_debug(
1727 : "%u: Routemap update-timer fired, scheduling RIB processing",
1728 : VRF_DEFAULT);
1729 :
1730 0 : route_map_walk_update_list(zebra_route_map_process_update_cb);
1731 :
1732 : /*
1733 : * This code needs to be updated to be:
1734 : * 1) VRF Aware <sigh>
1735 : * 2) Route-map aware
1736 : */
1737 0 : }
1738 :
1739 0 : static void zebra_route_map_set_delay_timer(uint32_t value)
1740 : {
1741 0 : zebra_rmap_update_timer = value;
1742 0 : if (!value && zebra_t_rmap_update) {
1743 : /* Event driven route map updates is being disabled */
1744 : /* But there's a pending timer. Fire it off now */
1745 0 : THREAD_OFF(zebra_t_rmap_update);
1746 0 : zebra_route_map_update_timer(NULL);
1747 : }
1748 0 : }
1749 :
1750 2 : void zebra_routemap_finish(void)
1751 : {
1752 : /* Set zebra_rmap_update_timer to 0 so that it wont schedule again */
1753 2 : zebra_rmap_update_timer = 0;
1754 : /* Thread off if any scheduled already */
1755 2 : THREAD_OFF(zebra_t_rmap_update);
1756 2 : route_map_finish();
1757 2 : }
1758 :
1759 : route_map_result_t
1760 0 : zebra_route_map_check(afi_t family, int rib_type, uint8_t instance,
1761 : const struct prefix *p, struct nexthop *nexthop,
1762 : struct zebra_vrf *zvrf, route_tag_t tag)
1763 : {
1764 0 : struct route_map *rmap = NULL;
1765 0 : char *rm_name;
1766 0 : route_map_result_t ret = RMAP_PERMITMATCH;
1767 0 : struct nh_rmap_obj nh_obj;
1768 :
1769 0 : nh_obj.nexthop = nexthop;
1770 0 : nh_obj.vrf_id = nexthop->vrf_id;
1771 0 : nh_obj.source_protocol = rib_type;
1772 0 : nh_obj.instance = instance;
1773 0 : nh_obj.metric = 0;
1774 0 : nh_obj.tag = tag;
1775 :
1776 0 : if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) {
1777 0 : rm_name = PROTO_RM_NAME(zvrf, family, rib_type);
1778 0 : rmap = PROTO_RM_MAP(zvrf, family, rib_type);
1779 :
1780 0 : if (rm_name && !rmap)
1781 : return RMAP_DENYMATCH;
1782 : }
1783 0 : if (!rmap) {
1784 0 : rm_name = PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX);
1785 0 : rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX);
1786 :
1787 0 : if (rm_name && !rmap)
1788 : return RMAP_DENYMATCH;
1789 : }
1790 0 : if (rmap) {
1791 0 : ret = route_map_apply(rmap, p, &nh_obj);
1792 : }
1793 :
1794 : return (ret);
1795 : }
1796 :
1797 0 : char *zebra_get_import_table_route_map(afi_t afi, uint32_t table)
1798 : {
1799 0 : return zebra_import_table_routemap[afi][table];
1800 : }
1801 :
1802 0 : void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name,
1803 : uint32_t table)
1804 : {
1805 0 : zebra_import_table_routemap[afi][table] =
1806 0 : XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
1807 0 : }
1808 :
1809 0 : void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
1810 : {
1811 0 : XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
1812 0 : }
1813 :
1814 : route_map_result_t
1815 0 : zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
1816 : const struct prefix *p,
1817 : struct nexthop *nexthop,
1818 : vrf_id_t vrf_id, route_tag_t tag,
1819 : const char *rmap_name)
1820 : {
1821 0 : struct route_map *rmap = NULL;
1822 0 : route_map_result_t ret = RMAP_DENYMATCH;
1823 0 : struct nh_rmap_obj nh_obj;
1824 :
1825 0 : nh_obj.nexthop = nexthop;
1826 0 : nh_obj.vrf_id = vrf_id;
1827 0 : nh_obj.source_protocol = re_type;
1828 0 : nh_obj.instance = instance;
1829 0 : nh_obj.metric = 0;
1830 0 : nh_obj.tag = tag;
1831 :
1832 0 : if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
1833 0 : rmap = route_map_lookup_by_name(rmap_name);
1834 0 : if (rmap) {
1835 0 : ret = route_map_apply(rmap, p, &nh_obj);
1836 : }
1837 :
1838 0 : return (ret);
1839 : }
1840 :
1841 0 : route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
1842 : const struct prefix *p,
1843 : struct zebra_vrf *zvrf,
1844 : struct route_entry *re,
1845 : struct nexthop *nexthop)
1846 : {
1847 0 : struct route_map *rmap = NULL;
1848 0 : route_map_result_t ret = RMAP_PERMITMATCH;
1849 0 : struct nh_rmap_obj nh_obj;
1850 :
1851 0 : nh_obj.nexthop = nexthop;
1852 0 : nh_obj.vrf_id = nexthop->vrf_id;
1853 0 : nh_obj.source_protocol = re->type;
1854 0 : nh_obj.instance = re->instance;
1855 0 : nh_obj.metric = re->metric;
1856 0 : nh_obj.tag = re->tag;
1857 :
1858 0 : if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
1859 0 : rmap = NHT_RM_MAP(zvrf, afi, client_proto);
1860 0 : if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX))
1861 : rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX);
1862 0 : if (rmap)
1863 0 : ret = route_map_apply(rmap, p, &nh_obj);
1864 :
1865 0 : return ret;
1866 : }
1867 :
1868 0 : static void zebra_route_map_mark_update(const char *rmap_name)
1869 : {
1870 : /* rmap_update_timer of 0 means don't do route updates */
1871 0 : if (zebra_rmap_update_timer)
1872 0 : THREAD_OFF(zebra_t_rmap_update);
1873 :
1874 0 : thread_add_timer(zrouter.master, zebra_route_map_update_timer,
1875 : NULL, zebra_rmap_update_timer, &zebra_t_rmap_update);
1876 0 : }
1877 :
1878 0 : static void zebra_route_map_add(const char *rmap_name)
1879 : {
1880 0 : if (route_map_mark_updated(rmap_name) == 0)
1881 0 : zebra_route_map_mark_update(rmap_name);
1882 :
1883 0 : route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1884 0 : }
1885 :
1886 0 : static void zebra_route_map_delete(const char *rmap_name)
1887 : {
1888 0 : if (route_map_mark_updated(rmap_name) == 0)
1889 0 : zebra_route_map_mark_update(rmap_name);
1890 :
1891 0 : route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
1892 0 : }
1893 :
1894 0 : static void zebra_route_map_event(const char *rmap_name)
1895 : {
1896 0 : if (route_map_mark_updated(rmap_name) == 0)
1897 0 : zebra_route_map_mark_update(rmap_name);
1898 :
1899 0 : route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
1900 0 : }
1901 :
1902 2 : void zebra_routemap_vrf_delete(struct zebra_vrf *zvrf)
1903 : {
1904 2 : afi_t afi;
1905 2 : uint8_t type;
1906 :
1907 8 : for (afi = AFI_IP; afi < AFI_MAX; afi++) {
1908 198 : for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
1909 192 : if (PROTO_RM_NAME(zvrf, afi, type))
1910 0 : XFREE(MTYPE_ROUTE_MAP_NAME,
1911 : PROTO_RM_NAME(zvrf, afi, type));
1912 192 : if (NHT_RM_NAME(zvrf, afi, type))
1913 192 : XFREE(MTYPE_ROUTE_MAP_NAME,
1914 : NHT_RM_NAME(zvrf, afi, type));
1915 : }
1916 : }
1917 2 : }
1918 :
1919 : /* ip protocol configuration write function */
1920 0 : void zebra_routemap_config_write_protocol(struct vty *vty,
1921 : struct zebra_vrf *zvrf)
1922 : {
1923 0 : int i;
1924 0 : char space[2];
1925 :
1926 0 : memset(space, 0, sizeof(space));
1927 :
1928 0 : if (zvrf_id(zvrf) != VRF_DEFAULT)
1929 0 : snprintf(space, sizeof(space), "%s", " ");
1930 :
1931 0 : for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1932 0 : if (PROTO_RM_NAME(zvrf, AFI_IP, i))
1933 0 : vty_out(vty, "%sip protocol %s route-map %s\n", space,
1934 : zebra_route_string(i),
1935 : PROTO_RM_NAME(zvrf, AFI_IP, i));
1936 :
1937 0 : if (PROTO_RM_NAME(zvrf, AFI_IP6, i))
1938 0 : vty_out(vty, "%sipv6 protocol %s route-map %s\n", space,
1939 : zebra_route_string(i),
1940 : PROTO_RM_NAME(zvrf, AFI_IP6, i));
1941 :
1942 0 : if (NHT_RM_NAME(zvrf, AFI_IP, i))
1943 0 : vty_out(vty, "%sip nht %s route-map %s\n", space,
1944 : zebra_route_string(i),
1945 : NHT_RM_NAME(zvrf, AFI_IP, i));
1946 :
1947 0 : if (NHT_RM_NAME(zvrf, AFI_IP6, i))
1948 0 : vty_out(vty, "%sipv6 nht %s route-map %s\n", space,
1949 : zebra_route_string(i),
1950 : NHT_RM_NAME(zvrf, AFI_IP6, i));
1951 : }
1952 :
1953 0 : if (PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1954 0 : vty_out(vty, "%sip protocol %s route-map %s\n", space, "any",
1955 : PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
1956 :
1957 0 : if (PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1958 0 : vty_out(vty, "%sipv6 protocol %s route-map %s\n", space, "any",
1959 : PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
1960 :
1961 0 : if (NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
1962 0 : vty_out(vty, "%sip nht %s route-map %s\n", space, "any",
1963 : NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
1964 :
1965 0 : if (NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
1966 0 : vty_out(vty, "%sipv6 nht %s route-map %s\n", space, "any",
1967 : NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
1968 :
1969 0 : if (zvrf_id(zvrf) == VRF_DEFAULT
1970 0 : && zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
1971 0 : vty_out(vty, "zebra route-map delay-timer %d\n",
1972 : zebra_rmap_update_timer);
1973 0 : }
1974 :
1975 2 : void zebra_route_map_init(void)
1976 : {
1977 2 : install_element(CONFIG_NODE, &ip_protocol_cmd);
1978 2 : install_element(CONFIG_NODE, &no_ip_protocol_cmd);
1979 2 : install_element(VRF_NODE, &ip_protocol_cmd);
1980 2 : install_element(VRF_NODE, &no_ip_protocol_cmd);
1981 2 : install_element(VIEW_NODE, &show_ip_protocol_cmd);
1982 2 : install_element(CONFIG_NODE, &ipv6_protocol_cmd);
1983 2 : install_element(CONFIG_NODE, &no_ipv6_protocol_cmd);
1984 2 : install_element(VRF_NODE, &ipv6_protocol_cmd);
1985 2 : install_element(VRF_NODE, &no_ipv6_protocol_cmd);
1986 2 : install_element(VIEW_NODE, &show_ipv6_protocol_cmd);
1987 2 : install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
1988 2 : install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
1989 2 : install_element(VRF_NODE, &ip_protocol_nht_rmap_cmd);
1990 2 : install_element(VRF_NODE, &no_ip_protocol_nht_rmap_cmd);
1991 2 : install_element(VIEW_NODE, &show_ip_protocol_nht_cmd);
1992 2 : install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
1993 2 : install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1994 2 : install_element(VRF_NODE, &ipv6_protocol_nht_rmap_cmd);
1995 2 : install_element(VRF_NODE, &no_ipv6_protocol_nht_rmap_cmd);
1996 2 : install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd);
1997 2 : install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
1998 2 : install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd);
1999 :
2000 2 : route_map_init();
2001 :
2002 2 : route_map_add_hook(zebra_route_map_add);
2003 2 : route_map_delete_hook(zebra_route_map_delete);
2004 2 : route_map_event_hook(zebra_route_map_event);
2005 :
2006 2 : route_map_match_interface_hook(generic_match_add);
2007 2 : route_map_no_match_interface_hook(generic_match_delete);
2008 :
2009 2 : route_map_match_ip_address_hook(generic_match_add);
2010 2 : route_map_no_match_ip_address_hook(generic_match_delete);
2011 :
2012 2 : route_map_match_ip_address_prefix_list_hook(generic_match_add);
2013 2 : route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
2014 :
2015 2 : route_map_match_ip_next_hop_hook(generic_match_add);
2016 2 : route_map_no_match_ip_next_hop_hook(generic_match_delete);
2017 :
2018 2 : route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
2019 2 : route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
2020 :
2021 2 : route_map_match_ip_next_hop_type_hook(generic_match_add);
2022 2 : route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
2023 :
2024 2 : route_map_match_tag_hook(generic_match_add);
2025 2 : route_map_no_match_tag_hook(generic_match_delete);
2026 :
2027 2 : route_map_match_ipv6_address_hook(generic_match_add);
2028 2 : route_map_no_match_ipv6_address_hook(generic_match_delete);
2029 :
2030 2 : route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
2031 2 : route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
2032 :
2033 2 : route_map_match_ipv6_next_hop_type_hook(generic_match_add);
2034 2 : route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
2035 :
2036 2 : route_map_install_match(&route_match_tag_cmd);
2037 2 : route_map_install_match(&route_match_interface_cmd);
2038 2 : route_map_install_match(&route_match_ip_next_hop_cmd);
2039 2 : route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
2040 2 : route_map_install_match(&route_match_ip_address_cmd);
2041 2 : route_map_install_match(&route_match_ipv6_address_cmd);
2042 2 : route_map_install_match(&route_match_ip_address_prefix_list_cmd);
2043 2 : route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
2044 2 : route_map_install_match(&route_match_ip_address_prefix_len_cmd);
2045 2 : route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
2046 2 : route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
2047 2 : route_map_install_match(&route_match_ip_next_hop_type_cmd);
2048 2 : route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
2049 2 : route_map_install_match(&route_match_source_protocol_cmd);
2050 2 : route_map_install_match(&route_match_source_instance_cmd);
2051 :
2052 : /* */
2053 2 : route_map_install_set(&route_set_src_cmd);
2054 : /* */
2055 2 : install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
2056 2 : install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
2057 2 : install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
2058 2 : install_element(RMAP_NODE, &match_ipv6_address_prefix_len_cmd);
2059 2 : install_element(RMAP_NODE, &no_match_ipv6_address_prefix_len_cmd);
2060 2 : install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
2061 2 : install_element(RMAP_NODE, &match_source_protocol_cmd);
2062 2 : install_element(RMAP_NODE, &no_match_source_protocol_cmd);
2063 2 : install_element(RMAP_NODE, &match_source_instance_cmd);
2064 2 : install_element(RMAP_NODE, &no_match_source_instance_cmd);
2065 :
2066 : /* */
2067 2 : install_element(RMAP_NODE, &set_src_cmd);
2068 2 : install_element(RMAP_NODE, &no_set_src_cmd);
2069 2 : }
|