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