]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* |
2 | * Route map function of ospfd. | |
3 | * Copyright (C) 2000 IP Infusion Inc. | |
4 | * | |
5 | * Written by Toshiaki Takada. | |
6 | * | |
7 | * This file is part of GNU Zebra. | |
8 | * | |
9 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
10 | * under the terms of the GNU General Public License as published by the | |
11 | * Free Software Foundation; either version 2, or (at your option) any | |
12 | * later version. | |
13 | * | |
14 | * GNU Zebra is distributed in the hope that it will be useful, but | |
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * General Public License for more details. | |
18 | * | |
896014f4 DL |
19 | * You should have received a copy of the GNU General Public License along |
20 | * with this program; see the file COPYING; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
718e3744 | 22 | */ |
23 | ||
24 | #include <zebra.h> | |
25 | ||
26 | #include "memory.h" | |
27 | #include "prefix.h" | |
28 | #include "table.h" | |
82f97584 | 29 | #include "vty.h" |
718e3744 | 30 | #include "routemap.h" |
31 | #include "command.h" | |
32 | #include "log.h" | |
33 | #include "plist.h" | |
1306c09a | 34 | #include "vrf.h" |
5d5ba018 | 35 | #include "frrstr.h" |
a623b526 | 36 | #include "northbound_cli.h" |
718e3744 | 37 | |
38 | #include "ospfd/ospfd.h" | |
39 | #include "ospfd/ospf_asbr.h" | |
40 | #include "ospfd/ospf_interface.h" | |
41 | #include "ospfd/ospf_lsa.h" | |
42 | #include "ospfd/ospf_route.h" | |
43 | #include "ospfd/ospf_zebra.h" | |
45301f8c | 44 | #include "ospfd/ospf_errors.h" |
718e3744 | 45 | |
46 | /* Hook function for updating route_map assignment. */ | |
d62a17ae | 47 | static void ospf_route_map_update(const char *name) |
48 | { | |
49 | struct ospf *ospf; | |
50 | int type; | |
b5a8894d | 51 | struct listnode *n1 = NULL; |
d62a17ae | 52 | |
53 | /* If OSPF instatnce does not exist, return right now. */ | |
b5a8894d | 54 | if (listcount(om->ospf) == 0) |
d62a17ae | 55 | return; |
56 | ||
43b8d1d8 | 57 | for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { |
b5a8894d CS |
58 | /* Update route-map */ |
59 | for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { | |
60 | struct list *red_list; | |
61 | struct listnode *node; | |
62 | struct ospf_redist *red; | |
63 | ||
64 | red_list = ospf->redist[type]; | |
65 | if (!red_list) | |
66 | continue; | |
67 | ||
68 | for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { | |
69 | if (ROUTEMAP_NAME(red) | |
70 | && strcmp(ROUTEMAP_NAME(red), name) == 0) { | |
71 | /* Keep old route-map. */ | |
72 | struct route_map *old = ROUTEMAP(red); | |
73 | ||
0fddd864 IR |
74 | ROUTEMAP(red) = |
75 | route_map_lookup_by_name( | |
76 | ROUTEMAP_NAME(red)); | |
77 | ||
78 | if (!old) | |
79 | route_map_counter_increment( | |
80 | ROUTEMAP(red)); | |
81 | ||
996c9314 LB |
82 | /* No update for this distribute type. |
83 | */ | |
84 | if (old == NULL | |
85 | && ROUTEMAP(red) == NULL) | |
b5a8894d CS |
86 | continue; |
87 | ||
996c9314 LB |
88 | ospf_distribute_list_update( |
89 | ospf, type, red->instance); | |
b5a8894d | 90 | } |
d62a17ae | 91 | } |
92 | } | |
93 | } | |
718e3744 | 94 | } |
95 | ||
097b5973 | 96 | static void ospf_route_map_event(const char *name) |
718e3744 | 97 | { |
d62a17ae | 98 | struct ospf *ospf; |
99 | int type; | |
b5a8894d CS |
100 | struct listnode *n1 = NULL; |
101 | ||
102 | for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { | |
103 | for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { | |
104 | struct list *red_list; | |
105 | struct listnode *node; | |
106 | struct ospf_redist *red; | |
107 | ||
108 | red_list = ospf->redist[type]; | |
109 | if (!red_list) | |
110 | continue; | |
111 | ||
112 | for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { | |
113 | if (ROUTEMAP_NAME(red) && ROUTEMAP(red) | |
114 | && !strcmp(ROUTEMAP_NAME(red), name)) { | |
996c9314 LB |
115 | ospf_distribute_list_update( |
116 | ospf, type, red->instance); | |
b5a8894d | 117 | } |
d62a17ae | 118 | } |
119 | } | |
120 | } | |
718e3744 | 121 | } |
122 | ||
718e3744 | 123 | /* `match ip netxthop ' */ |
124 | /* Match function return 1 if match is success else return zero. */ | |
b68885f9 | 125 | static enum route_map_cmd_result_t |
1782514f | 126 | route_match_ip_nexthop(void *rule, const struct prefix *prefix, void *object) |
d62a17ae | 127 | { |
128 | struct access_list *alist; | |
129 | struct external_info *ei = object; | |
130 | struct prefix_ipv4 p; | |
131 | ||
1782514f DS |
132 | p.family = AF_INET; |
133 | p.prefix = ei->nexthop; | |
134 | p.prefixlen = IPV4_MAX_BITLEN; | |
d62a17ae | 135 | |
1782514f DS |
136 | alist = access_list_lookup(AFI_IP, (char *)rule); |
137 | if (alist == NULL) | |
138 | return RMAP_NOMATCH; | |
d62a17ae | 139 | |
1782514f DS |
140 | return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH |
141 | : RMAP_MATCH); | |
718e3744 | 142 | } |
143 | ||
144 | /* Route map `ip next-hop' match statement. `arg' should be | |
145 | access-list name. */ | |
d62a17ae | 146 | static void *route_match_ip_nexthop_compile(const char *arg) |
718e3744 | 147 | { |
d62a17ae | 148 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 149 | } |
150 | ||
151 | /* Free route map's compiled `ip address' value. */ | |
d62a17ae | 152 | static void route_match_ip_nexthop_free(void *rule) |
718e3744 | 153 | { |
d62a17ae | 154 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 155 | } |
156 | ||
157 | /* Route map commands for metric matching. */ | |
364deb04 DL |
158 | static const struct route_map_rule_cmd route_match_ip_nexthop_cmd = { |
159 | "ip next-hop", | |
160 | route_match_ip_nexthop, | |
161 | route_match_ip_nexthop_compile, | |
162 | route_match_ip_nexthop_free | |
163 | }; | |
718e3744 | 164 | |
165 | /* `match ip next-hop prefix-list PREFIX_LIST' */ | |
166 | ||
b68885f9 | 167 | static enum route_map_cmd_result_t |
123214ef | 168 | route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, |
1782514f | 169 | void *object) |
718e3744 | 170 | { |
d62a17ae | 171 | struct prefix_list *plist; |
172 | struct external_info *ei = object; | |
173 | struct prefix_ipv4 p; | |
174 | ||
1782514f DS |
175 | p.family = AF_INET; |
176 | p.prefix = ei->nexthop; | |
177 | p.prefixlen = IPV4_MAX_BITLEN; | |
d62a17ae | 178 | |
1782514f DS |
179 | plist = prefix_list_lookup(AFI_IP, (char *)rule); |
180 | if (plist == NULL) | |
181 | return RMAP_NOMATCH; | |
d62a17ae | 182 | |
1782514f DS |
183 | return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH |
184 | : RMAP_MATCH); | |
718e3744 | 185 | } |
186 | ||
d62a17ae | 187 | static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) |
718e3744 | 188 | { |
d62a17ae | 189 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 190 | } |
191 | ||
d62a17ae | 192 | static void route_match_ip_next_hop_prefix_list_free(void *rule) |
718e3744 | 193 | { |
d62a17ae | 194 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 195 | } |
196 | ||
364deb04 DL |
197 | static const struct route_map_rule_cmd |
198 | route_match_ip_next_hop_prefix_list_cmd = { | |
199 | "ip next-hop prefix-list", | |
200 | route_match_ip_next_hop_prefix_list, | |
d62a17ae | 201 | route_match_ip_next_hop_prefix_list_compile, |
364deb04 DL |
202 | route_match_ip_next_hop_prefix_list_free |
203 | }; | |
718e3744 | 204 | |
b6c0e913 DA |
205 | /* `match ip next-hop type <blackhole>' */ |
206 | ||
b68885f9 | 207 | static enum route_map_cmd_result_t |
b6c0e913 | 208 | route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, |
1782514f | 209 | void *object) |
b6c0e913 DA |
210 | { |
211 | struct external_info *ei = object; | |
212 | ||
1782514f | 213 | if (prefix->family == AF_INET) { |
b6c0e913 DA |
214 | ei = (struct external_info *)object; |
215 | if (!ei) | |
b68885f9 | 216 | return RMAP_NOMATCH; |
b6c0e913 DA |
217 | |
218 | if (ei->nexthop.s_addr == INADDR_ANY && !ei->ifindex) | |
219 | return RMAP_MATCH; | |
220 | } | |
221 | return RMAP_NOMATCH; | |
222 | } | |
223 | ||
224 | static void *route_match_ip_next_hop_type_compile(const char *arg) | |
225 | { | |
226 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); | |
227 | } | |
228 | ||
229 | static void route_match_ip_next_hop_type_free(void *rule) | |
230 | { | |
231 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); | |
232 | } | |
233 | ||
364deb04 DL |
234 | static const struct route_map_rule_cmd |
235 | route_match_ip_next_hop_type_cmd = { | |
236 | "ip next-hop type", | |
237 | route_match_ip_next_hop_type, | |
b6c0e913 | 238 | route_match_ip_next_hop_type_compile, |
364deb04 DL |
239 | route_match_ip_next_hop_type_free |
240 | }; | |
b6c0e913 | 241 | |
718e3744 | 242 | /* `match ip address IP_ACCESS_LIST' */ |
243 | /* Match function should return 1 if match is success else return | |
244 | zero. */ | |
b68885f9 | 245 | static enum route_map_cmd_result_t |
1782514f | 246 | route_match_ip_address(void *rule, const struct prefix *prefix, void *object) |
d62a17ae | 247 | { |
248 | struct access_list *alist; | |
249 | /* struct prefix_ipv4 match; */ | |
250 | ||
1782514f DS |
251 | alist = access_list_lookup(AFI_IP, (char *)rule); |
252 | if (alist == NULL) | |
253 | return RMAP_NOMATCH; | |
d62a17ae | 254 | |
1782514f DS |
255 | return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH |
256 | : RMAP_MATCH); | |
718e3744 | 257 | } |
258 | ||
259 | /* Route map `ip address' match statement. `arg' should be | |
260 | access-list name. */ | |
d62a17ae | 261 | static void *route_match_ip_address_compile(const char *arg) |
718e3744 | 262 | { |
d62a17ae | 263 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 264 | } |
265 | ||
266 | /* Free route map's compiled `ip address' value. */ | |
d62a17ae | 267 | static void route_match_ip_address_free(void *rule) |
718e3744 | 268 | { |
d62a17ae | 269 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 270 | } |
271 | ||
272 | /* Route map commands for ip address matching. */ | |
364deb04 DL |
273 | static const struct route_map_rule_cmd route_match_ip_address_cmd = { |
274 | "ip address", | |
275 | route_match_ip_address, | |
276 | route_match_ip_address_compile, | |
277 | route_match_ip_address_free | |
278 | }; | |
718e3744 | 279 | |
280 | /* `match ip address prefix-list PREFIX_LIST' */ | |
b68885f9 | 281 | static enum route_map_cmd_result_t |
123214ef | 282 | route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, |
1782514f | 283 | void *object) |
718e3744 | 284 | { |
d62a17ae | 285 | struct prefix_list *plist; |
286 | ||
1782514f DS |
287 | plist = prefix_list_lookup(AFI_IP, (char *)rule); |
288 | if (plist == NULL) | |
289 | return RMAP_NOMATCH; | |
d62a17ae | 290 | |
1782514f DS |
291 | return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH |
292 | : RMAP_MATCH); | |
718e3744 | 293 | } |
294 | ||
d62a17ae | 295 | static void *route_match_ip_address_prefix_list_compile(const char *arg) |
718e3744 | 296 | { |
d62a17ae | 297 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 298 | } |
299 | ||
d62a17ae | 300 | static void route_match_ip_address_prefix_list_free(void *rule) |
718e3744 | 301 | { |
d62a17ae | 302 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 303 | } |
304 | ||
364deb04 DL |
305 | static const struct route_map_rule_cmd |
306 | route_match_ip_address_prefix_list_cmd = { | |
307 | "ip address prefix-list", | |
308 | route_match_ip_address_prefix_list, | |
d62a17ae | 309 | route_match_ip_address_prefix_list_compile, |
364deb04 DL |
310 | route_match_ip_address_prefix_list_free |
311 | }; | |
718e3744 | 312 | |
313 | /* `match interface IFNAME' */ | |
314 | /* Match function should return 1 if match is success else return | |
315 | zero. */ | |
b68885f9 | 316 | static enum route_map_cmd_result_t |
1782514f | 317 | route_match_interface(void *rule, const struct prefix *prefix, void *object) |
718e3744 | 318 | { |
d62a17ae | 319 | struct interface *ifp; |
320 | struct external_info *ei; | |
718e3744 | 321 | |
1782514f DS |
322 | ei = object; |
323 | ifp = if_lookup_by_name_all_vrf((char *)rule); | |
718e3744 | 324 | |
1782514f DS |
325 | if (ifp == NULL || ifp->ifindex != ei->ifindex) |
326 | return RMAP_NOMATCH; | |
718e3744 | 327 | |
1782514f | 328 | return RMAP_MATCH; |
718e3744 | 329 | } |
330 | ||
331 | /* Route map `interface' match statement. `arg' should be | |
332 | interface name. */ | |
d62a17ae | 333 | static void *route_match_interface_compile(const char *arg) |
718e3744 | 334 | { |
d62a17ae | 335 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 336 | } |
337 | ||
338 | /* Free route map's compiled `interface' value. */ | |
d62a17ae | 339 | static void route_match_interface_free(void *rule) |
718e3744 | 340 | { |
d62a17ae | 341 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 342 | } |
343 | ||
344 | /* Route map commands for ip address matching. */ | |
364deb04 DL |
345 | static const struct route_map_rule_cmd route_match_interface_cmd = { |
346 | "interface", | |
347 | route_match_interface, | |
348 | route_match_interface_compile, | |
349 | route_match_interface_free | |
350 | }; | |
718e3744 | 351 | |
0d9551dc | 352 | /* Match function return 1 if match is success else return zero. */ |
b68885f9 | 353 | static enum route_map_cmd_result_t |
1782514f | 354 | route_match_tag(void *rule, const struct prefix *prefix, void *object) |
0d9551dc | 355 | { |
d62a17ae | 356 | route_tag_t *tag; |
357 | struct external_info *ei; | |
0d9551dc | 358 | |
1782514f DS |
359 | tag = rule; |
360 | ei = object; | |
0d9551dc | 361 | |
1782514f | 362 | return ((ei->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH); |
0d9551dc DS |
363 | } |
364 | ||
0d9551dc | 365 | /* Route map commands for tag matching. */ |
364deb04 DL |
366 | static const struct route_map_rule_cmd route_match_tag_cmd = { |
367 | "tag", | |
368 | route_match_tag, | |
369 | route_map_rule_tag_compile, | |
d62a17ae | 370 | route_map_rule_tag_free, |
0d9551dc DS |
371 | }; |
372 | ||
6a74c5f9 | 373 | struct ospf_metric { |
7a5e6e46 | 374 | enum { metric_increment, metric_decrement, metric_absolute } type; |
6a74c5f9 | 375 | bool used; |
d7c0a89a | 376 | uint32_t metric; |
6a74c5f9 | 377 | }; |
0d9551dc | 378 | |
718e3744 | 379 | /* `set metric METRIC' */ |
380 | /* Set metric to attribute. */ | |
b68885f9 | 381 | static enum route_map_cmd_result_t |
1782514f | 382 | route_set_metric(void *rule, const struct prefix *prefix, void *object) |
718e3744 | 383 | { |
6a74c5f9 | 384 | struct ospf_metric *metric; |
d62a17ae | 385 | struct external_info *ei; |
386 | ||
1782514f DS |
387 | /* Fetch routemap's rule information. */ |
388 | metric = rule; | |
389 | ei = object; | |
d62a17ae | 390 | |
1782514f DS |
391 | /* Set metric out value. */ |
392 | if (!metric->used) | |
393 | return RMAP_OKAY; | |
236e900c | 394 | |
1782514f | 395 | ei->route_map_set.metric = DEFAULT_DEFAULT_METRIC; |
236e900c | 396 | |
1782514f DS |
397 | if (metric->type == metric_increment) |
398 | ei->route_map_set.metric += metric->metric; | |
399 | else if (metric->type == metric_decrement) | |
400 | ei->route_map_set.metric -= metric->metric; | |
401 | else if (metric->type == metric_absolute) | |
402 | ei->route_map_set.metric = metric->metric; | |
403 | ||
404 | if (ei->route_map_set.metric > OSPF_LS_INFINITY) | |
405 | ei->route_map_set.metric = OSPF_LS_INFINITY; | |
7a5e6e46 | 406 | |
d62a17ae | 407 | return RMAP_OKAY; |
718e3744 | 408 | } |
409 | ||
410 | /* set metric compilation. */ | |
d62a17ae | 411 | static void *route_set_metric_compile(const char *arg) |
412 | { | |
6a74c5f9 DS |
413 | struct ospf_metric *metric; |
414 | ||
cf0f13de | 415 | metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*metric)); |
6a74c5f9 | 416 | metric->used = false; |
d62a17ae | 417 | |
7a5e6e46 | 418 | if (all_digit(arg)) |
419 | metric->type = metric_absolute; | |
420 | ||
421 | if (strmatch(arg, "+rtt") || strmatch(arg, "-rtt")) { | |
cf444bcf | 422 | flog_warn(EC_OSPF_SET_METRIC_PLUS, |
45301f8c | 423 | "OSPF does not support 'set metric +rtt / -rtt'"); |
7a5e6e46 | 424 | return metric; |
425 | } | |
426 | ||
427 | if ((arg[0] == '+') && all_digit(arg + 1)) { | |
428 | metric->type = metric_increment; | |
429 | arg++; | |
ed2eb093 | 430 | } |
7a5e6e46 | 431 | |
432 | if ((arg[0] == '-') && all_digit(arg + 1)) { | |
433 | metric->type = metric_decrement; | |
434 | arg++; | |
435 | } | |
436 | ||
6a74c5f9 | 437 | metric->metric = strtoul(arg, NULL, 10); |
7a5e6e46 | 438 | |
439 | if (metric->metric) | |
440 | metric->used = true; | |
d62a17ae | 441 | |
442 | return metric; | |
718e3744 | 443 | } |
444 | ||
445 | /* Free route map's compiled `set metric' value. */ | |
d62a17ae | 446 | static void route_set_metric_free(void *rule) |
718e3744 | 447 | { |
d62a17ae | 448 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 449 | } |
450 | ||
451 | /* Set metric rule structure. */ | |
364deb04 DL |
452 | static const struct route_map_rule_cmd route_set_metric_cmd = { |
453 | "metric", | |
454 | route_set_metric, | |
455 | route_set_metric_compile, | |
d62a17ae | 456 | route_set_metric_free, |
718e3744 | 457 | }; |
458 | ||
459 | /* `set metric-type TYPE' */ | |
460 | /* Set metric-type to attribute. */ | |
b68885f9 | 461 | static enum route_map_cmd_result_t |
1782514f | 462 | route_set_metric_type(void *rule, const struct prefix *prefix, void *object) |
718e3744 | 463 | { |
d7c0a89a | 464 | uint32_t *metric_type; |
d62a17ae | 465 | struct external_info *ei; |
466 | ||
1782514f DS |
467 | /* Fetch routemap's rule information. */ |
468 | metric_type = rule; | |
469 | ei = object; | |
470 | ||
471 | /* Set metric out value. */ | |
472 | ei->route_map_set.metric_type = *metric_type; | |
d62a17ae | 473 | |
d62a17ae | 474 | return RMAP_OKAY; |
718e3744 | 475 | } |
476 | ||
477 | /* set metric-type compilation. */ | |
d62a17ae | 478 | static void *route_set_metric_type_compile(const char *arg) |
718e3744 | 479 | { |
d7c0a89a | 480 | uint32_t *metric_type; |
718e3744 | 481 | |
d7c0a89a | 482 | metric_type = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t)); |
d62a17ae | 483 | if (strcmp(arg, "type-1") == 0) |
484 | *metric_type = EXTERNAL_METRIC_TYPE_1; | |
485 | else if (strcmp(arg, "type-2") == 0) | |
486 | *metric_type = EXTERNAL_METRIC_TYPE_2; | |
718e3744 | 487 | |
d62a17ae | 488 | if (*metric_type == EXTERNAL_METRIC_TYPE_1 |
489 | || *metric_type == EXTERNAL_METRIC_TYPE_2) | |
490 | return metric_type; | |
718e3744 | 491 | |
d62a17ae | 492 | XFREE(MTYPE_ROUTE_MAP_COMPILED, metric_type); |
493 | return NULL; | |
718e3744 | 494 | } |
495 | ||
496 | /* Free route map's compiled `set metric-type' value. */ | |
d62a17ae | 497 | static void route_set_metric_type_free(void *rule) |
718e3744 | 498 | { |
d62a17ae | 499 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 500 | } |
501 | ||
502 | /* Set metric rule structure. */ | |
364deb04 DL |
503 | static const struct route_map_rule_cmd route_set_metric_type_cmd = { |
504 | "metric-type", | |
505 | route_set_metric_type, | |
506 | route_set_metric_type_compile, | |
d62a17ae | 507 | route_set_metric_type_free, |
718e3744 | 508 | }; |
509 | ||
b68885f9 | 510 | static enum route_map_cmd_result_t |
1782514f | 511 | route_set_tag(void *rule, const struct prefix *prefix, void *object) |
0d9551dc | 512 | { |
d62a17ae | 513 | route_tag_t *tag; |
514 | struct external_info *ei; | |
0d9551dc | 515 | |
1782514f DS |
516 | tag = rule; |
517 | ei = object; | |
0d9551dc | 518 | |
1782514f DS |
519 | /* Set tag value */ |
520 | ei->tag = *tag; | |
0d9551dc | 521 | |
d62a17ae | 522 | return RMAP_OKAY; |
0d9551dc DS |
523 | } |
524 | ||
0d9551dc | 525 | /* Route map commands for tag set. */ |
364deb04 DL |
526 | static const struct route_map_rule_cmd route_set_tag_cmd = { |
527 | "tag", | |
528 | route_set_tag, | |
529 | route_map_rule_tag_compile, | |
d62a17ae | 530 | route_map_rule_tag_free, |
0d9551dc DS |
531 | }; |
532 | ||
a623b526 | 533 | DEFUN_YANG (set_metric_type, |
718e3744 | 534 | set_metric_type_cmd, |
6147e2c6 | 535 | "set metric-type <type-1|type-2>", |
718e3744 | 536 | SET_STR |
537 | "Type of metric for destination routing protocol\n" | |
73ffb25b | 538 | "OSPF[6] external type 1 metric\n" |
539 | "OSPF[6] external type 2 metric\n") | |
718e3744 | 540 | { |
d62a17ae | 541 | char *ext = argv[2]->text; |
a623b526 SP |
542 | |
543 | const char *xpath = | |
544 | "./set-action[action='frr-ospf-route-map:metric-type']"; | |
545 | char xpath_value[XPATH_MAXLEN]; | |
546 | ||
547 | nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); | |
548 | snprintf(xpath_value, sizeof(xpath_value), | |
549 | "%s/rmap-set-action/frr-ospf-route-map:metric-type", xpath); | |
550 | nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ext); | |
551 | return nb_cli_apply_changes(vty, NULL); | |
718e3744 | 552 | } |
553 | ||
a623b526 | 554 | DEFUN_YANG (no_set_metric_type, |
718e3744 | 555 | no_set_metric_type_cmd, |
692b4c65 | 556 | "no set metric-type [<type-1|type-2>]", |
718e3744 | 557 | NO_STR |
558 | SET_STR | |
ff788d08 | 559 | "Type of metric for destination routing protocol\n" |
692b4c65 | 560 | "OSPF[6] external type 1 metric\n" |
ff788d08 | 561 | "OSPF[6] external type 2 metric\n") |
718e3744 | 562 | { |
a623b526 SP |
563 | const char *xpath = |
564 | "./set-action[action='frr-ospf-route-map:metric-type']"; | |
565 | ||
566 | nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); | |
567 | return nb_cli_apply_changes(vty, NULL); | |
0d9551dc DS |
568 | } |
569 | ||
718e3744 | 570 | /* Route-map init */ |
d62a17ae | 571 | void ospf_route_map_init(void) |
718e3744 | 572 | { |
d62a17ae | 573 | route_map_init(); |
574 | ||
575 | route_map_add_hook(ospf_route_map_update); | |
576 | route_map_delete_hook(ospf_route_map_update); | |
577 | route_map_event_hook(ospf_route_map_event); | |
718e3744 | 578 | |
d62a17ae | 579 | route_map_set_metric_hook(generic_set_add); |
580 | route_map_no_set_metric_hook(generic_set_delete); | |
82f97584 | 581 | |
d62a17ae | 582 | route_map_match_ip_next_hop_hook(generic_match_add); |
583 | route_map_no_match_ip_next_hop_hook(generic_match_delete); | |
58b0878a | 584 | |
d62a17ae | 585 | route_map_match_interface_hook(generic_match_add); |
586 | route_map_no_match_interface_hook(generic_match_delete); | |
58b0878a | 587 | |
d62a17ae | 588 | route_map_match_ip_address_hook(generic_match_add); |
589 | route_map_no_match_ip_address_hook(generic_match_delete); | |
82f97584 | 590 | |
d62a17ae | 591 | route_map_match_ip_address_prefix_list_hook(generic_match_add); |
592 | route_map_no_match_ip_address_prefix_list_hook(generic_match_delete); | |
82f97584 | 593 | |
d62a17ae | 594 | route_map_match_ip_next_hop_prefix_list_hook(generic_match_add); |
595 | route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete); | |
82f97584 | 596 | |
b6c0e913 DA |
597 | route_map_match_ip_next_hop_type_hook(generic_match_add); |
598 | route_map_no_match_ip_next_hop_type_hook(generic_match_delete); | |
599 | ||
d62a17ae | 600 | route_map_match_tag_hook(generic_match_add); |
601 | route_map_no_match_tag_hook(generic_match_delete); | |
82f97584 | 602 | |
d62a17ae | 603 | route_map_set_metric_hook(generic_set_add); |
604 | route_map_no_set_metric_hook(generic_set_delete); | |
82f97584 | 605 | |
d62a17ae | 606 | route_map_set_tag_hook(generic_set_add); |
607 | route_map_no_set_tag_hook(generic_set_delete); | |
82f97584 | 608 | |
d62a17ae | 609 | route_map_install_match(&route_match_ip_nexthop_cmd); |
610 | route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd); | |
611 | route_map_install_match(&route_match_ip_address_cmd); | |
612 | route_map_install_match(&route_match_ip_address_prefix_list_cmd); | |
b6c0e913 | 613 | route_map_install_match(&route_match_ip_next_hop_type_cmd); |
d62a17ae | 614 | route_map_install_match(&route_match_interface_cmd); |
615 | route_map_install_match(&route_match_tag_cmd); | |
718e3744 | 616 | |
d62a17ae | 617 | route_map_install_set(&route_set_metric_cmd); |
618 | route_map_install_set(&route_set_metric_type_cmd); | |
619 | route_map_install_set(&route_set_tag_cmd); | |
718e3744 | 620 | |
d62a17ae | 621 | install_element(RMAP_NODE, &set_metric_type_cmd); |
622 | install_element(RMAP_NODE, &no_set_metric_type_cmd); | |
718e3744 | 623 | } |