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