]>
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 | 136 | alist = access_list_lookup(AFI_IP, (char *)rule); |
46b2a036 DS |
137 | if (alist == NULL) { |
138 | if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) | |
139 | zlog_debug( | |
140 | "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", | |
141 | __func__, (char *)rule); | |
1782514f | 142 | return RMAP_NOMATCH; |
46b2a036 | 143 | } |
d62a17ae | 144 | |
1782514f DS |
145 | return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH |
146 | : RMAP_MATCH); | |
718e3744 | 147 | } |
148 | ||
149 | /* Route map `ip next-hop' match statement. `arg' should be | |
150 | access-list name. */ | |
d62a17ae | 151 | static void *route_match_ip_nexthop_compile(const char *arg) |
718e3744 | 152 | { |
d62a17ae | 153 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 154 | } |
155 | ||
156 | /* Free route map's compiled `ip address' value. */ | |
d62a17ae | 157 | static void route_match_ip_nexthop_free(void *rule) |
718e3744 | 158 | { |
d62a17ae | 159 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 160 | } |
161 | ||
162 | /* Route map commands for metric matching. */ | |
364deb04 DL |
163 | static const struct route_map_rule_cmd route_match_ip_nexthop_cmd = { |
164 | "ip next-hop", | |
165 | route_match_ip_nexthop, | |
166 | route_match_ip_nexthop_compile, | |
167 | route_match_ip_nexthop_free | |
168 | }; | |
718e3744 | 169 | |
170 | /* `match ip next-hop prefix-list PREFIX_LIST' */ | |
171 | ||
b68885f9 | 172 | static enum route_map_cmd_result_t |
123214ef | 173 | route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, |
1782514f | 174 | void *object) |
718e3744 | 175 | { |
d62a17ae | 176 | struct prefix_list *plist; |
177 | struct external_info *ei = object; | |
178 | struct prefix_ipv4 p; | |
179 | ||
1782514f DS |
180 | p.family = AF_INET; |
181 | p.prefix = ei->nexthop; | |
182 | p.prefixlen = IPV4_MAX_BITLEN; | |
d62a17ae | 183 | |
1782514f DS |
184 | plist = prefix_list_lookup(AFI_IP, (char *)rule); |
185 | if (plist == NULL) | |
186 | return RMAP_NOMATCH; | |
d62a17ae | 187 | |
1782514f DS |
188 | return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH |
189 | : RMAP_MATCH); | |
718e3744 | 190 | } |
191 | ||
d62a17ae | 192 | static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) |
718e3744 | 193 | { |
d62a17ae | 194 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 195 | } |
196 | ||
d62a17ae | 197 | static void route_match_ip_next_hop_prefix_list_free(void *rule) |
718e3744 | 198 | { |
d62a17ae | 199 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 200 | } |
201 | ||
364deb04 DL |
202 | static const struct route_map_rule_cmd |
203 | route_match_ip_next_hop_prefix_list_cmd = { | |
204 | "ip next-hop prefix-list", | |
205 | route_match_ip_next_hop_prefix_list, | |
d62a17ae | 206 | route_match_ip_next_hop_prefix_list_compile, |
364deb04 DL |
207 | route_match_ip_next_hop_prefix_list_free |
208 | }; | |
718e3744 | 209 | |
b6c0e913 DA |
210 | /* `match ip next-hop type <blackhole>' */ |
211 | ||
b68885f9 | 212 | static enum route_map_cmd_result_t |
b6c0e913 | 213 | route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, |
1782514f | 214 | void *object) |
b6c0e913 DA |
215 | { |
216 | struct external_info *ei = object; | |
217 | ||
1782514f | 218 | if (prefix->family == AF_INET) { |
b6c0e913 DA |
219 | ei = (struct external_info *)object; |
220 | if (!ei) | |
b68885f9 | 221 | return RMAP_NOMATCH; |
b6c0e913 DA |
222 | |
223 | if (ei->nexthop.s_addr == INADDR_ANY && !ei->ifindex) | |
224 | return RMAP_MATCH; | |
225 | } | |
226 | return RMAP_NOMATCH; | |
227 | } | |
228 | ||
229 | static void *route_match_ip_next_hop_type_compile(const char *arg) | |
230 | { | |
231 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); | |
232 | } | |
233 | ||
234 | static void route_match_ip_next_hop_type_free(void *rule) | |
235 | { | |
236 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); | |
237 | } | |
238 | ||
364deb04 DL |
239 | static const struct route_map_rule_cmd |
240 | route_match_ip_next_hop_type_cmd = { | |
241 | "ip next-hop type", | |
242 | route_match_ip_next_hop_type, | |
b6c0e913 | 243 | route_match_ip_next_hop_type_compile, |
364deb04 DL |
244 | route_match_ip_next_hop_type_free |
245 | }; | |
b6c0e913 | 246 | |
718e3744 | 247 | /* `match ip address IP_ACCESS_LIST' */ |
248 | /* Match function should return 1 if match is success else return | |
249 | zero. */ | |
b68885f9 | 250 | static enum route_map_cmd_result_t |
1782514f | 251 | route_match_ip_address(void *rule, const struct prefix *prefix, void *object) |
d62a17ae | 252 | { |
253 | struct access_list *alist; | |
254 | /* struct prefix_ipv4 match; */ | |
255 | ||
1782514f | 256 | alist = access_list_lookup(AFI_IP, (char *)rule); |
46b2a036 DS |
257 | if (alist == NULL) { |
258 | if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) | |
259 | zlog_debug( | |
260 | "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH", | |
261 | __func__, (char *)rule); | |
1782514f | 262 | return RMAP_NOMATCH; |
46b2a036 | 263 | } |
d62a17ae | 264 | |
1782514f DS |
265 | return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH |
266 | : RMAP_MATCH); | |
718e3744 | 267 | } |
268 | ||
269 | /* Route map `ip address' match statement. `arg' should be | |
270 | access-list name. */ | |
d62a17ae | 271 | static void *route_match_ip_address_compile(const char *arg) |
718e3744 | 272 | { |
d62a17ae | 273 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 274 | } |
275 | ||
276 | /* Free route map's compiled `ip address' value. */ | |
d62a17ae | 277 | static void route_match_ip_address_free(void *rule) |
718e3744 | 278 | { |
d62a17ae | 279 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 280 | } |
281 | ||
282 | /* Route map commands for ip address matching. */ | |
364deb04 DL |
283 | static const struct route_map_rule_cmd route_match_ip_address_cmd = { |
284 | "ip address", | |
285 | route_match_ip_address, | |
286 | route_match_ip_address_compile, | |
287 | route_match_ip_address_free | |
288 | }; | |
718e3744 | 289 | |
290 | /* `match ip address prefix-list PREFIX_LIST' */ | |
b68885f9 | 291 | static enum route_map_cmd_result_t |
123214ef | 292 | route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, |
1782514f | 293 | void *object) |
718e3744 | 294 | { |
d62a17ae | 295 | struct prefix_list *plist; |
296 | ||
1782514f DS |
297 | plist = prefix_list_lookup(AFI_IP, (char *)rule); |
298 | if (plist == NULL) | |
299 | return RMAP_NOMATCH; | |
d62a17ae | 300 | |
1782514f DS |
301 | return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH |
302 | : RMAP_MATCH); | |
718e3744 | 303 | } |
304 | ||
d62a17ae | 305 | static void *route_match_ip_address_prefix_list_compile(const char *arg) |
718e3744 | 306 | { |
d62a17ae | 307 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 308 | } |
309 | ||
d62a17ae | 310 | static void route_match_ip_address_prefix_list_free(void *rule) |
718e3744 | 311 | { |
d62a17ae | 312 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 313 | } |
314 | ||
364deb04 DL |
315 | static const struct route_map_rule_cmd |
316 | route_match_ip_address_prefix_list_cmd = { | |
317 | "ip address prefix-list", | |
318 | route_match_ip_address_prefix_list, | |
d62a17ae | 319 | route_match_ip_address_prefix_list_compile, |
364deb04 DL |
320 | route_match_ip_address_prefix_list_free |
321 | }; | |
718e3744 | 322 | |
323 | /* `match interface IFNAME' */ | |
324 | /* Match function should return 1 if match is success else return | |
325 | zero. */ | |
b68885f9 | 326 | static enum route_map_cmd_result_t |
1782514f | 327 | route_match_interface(void *rule, const struct prefix *prefix, void *object) |
718e3744 | 328 | { |
d62a17ae | 329 | struct interface *ifp; |
330 | struct external_info *ei; | |
718e3744 | 331 | |
1782514f | 332 | ei = object; |
4030e186 | 333 | ifp = if_lookup_by_name((char *)rule, ei->ospf->vrf_id); |
718e3744 | 334 | |
1782514f DS |
335 | if (ifp == NULL || ifp->ifindex != ei->ifindex) |
336 | return RMAP_NOMATCH; | |
718e3744 | 337 | |
1782514f | 338 | return RMAP_MATCH; |
718e3744 | 339 | } |
340 | ||
341 | /* Route map `interface' match statement. `arg' should be | |
342 | interface name. */ | |
d62a17ae | 343 | static void *route_match_interface_compile(const char *arg) |
718e3744 | 344 | { |
d62a17ae | 345 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
718e3744 | 346 | } |
347 | ||
348 | /* Free route map's compiled `interface' value. */ | |
d62a17ae | 349 | static void route_match_interface_free(void *rule) |
718e3744 | 350 | { |
d62a17ae | 351 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 352 | } |
353 | ||
354 | /* Route map commands for ip address matching. */ | |
364deb04 DL |
355 | static const struct route_map_rule_cmd route_match_interface_cmd = { |
356 | "interface", | |
357 | route_match_interface, | |
358 | route_match_interface_compile, | |
359 | route_match_interface_free | |
360 | }; | |
718e3744 | 361 | |
0d9551dc | 362 | /* Match function return 1 if match is success else return zero. */ |
b68885f9 | 363 | static enum route_map_cmd_result_t |
1782514f | 364 | route_match_tag(void *rule, const struct prefix *prefix, void *object) |
0d9551dc | 365 | { |
d62a17ae | 366 | route_tag_t *tag; |
367 | struct external_info *ei; | |
0d9551dc | 368 | |
1782514f DS |
369 | tag = rule; |
370 | ei = object; | |
0d9551dc | 371 | |
1782514f | 372 | return ((ei->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH); |
0d9551dc DS |
373 | } |
374 | ||
0d9551dc | 375 | /* Route map commands for tag matching. */ |
364deb04 DL |
376 | static const struct route_map_rule_cmd route_match_tag_cmd = { |
377 | "tag", | |
378 | route_match_tag, | |
379 | route_map_rule_tag_compile, | |
d62a17ae | 380 | route_map_rule_tag_free, |
0d9551dc DS |
381 | }; |
382 | ||
6a74c5f9 | 383 | struct ospf_metric { |
7a5e6e46 | 384 | enum { metric_increment, metric_decrement, metric_absolute } type; |
6a74c5f9 | 385 | bool used; |
d7c0a89a | 386 | uint32_t metric; |
6a74c5f9 | 387 | }; |
0d9551dc | 388 | |
718e3744 | 389 | /* `set metric METRIC' */ |
390 | /* Set metric to attribute. */ | |
b68885f9 | 391 | static enum route_map_cmd_result_t |
1782514f | 392 | route_set_metric(void *rule, const struct prefix *prefix, void *object) |
718e3744 | 393 | { |
6a74c5f9 | 394 | struct ospf_metric *metric; |
d62a17ae | 395 | struct external_info *ei; |
396 | ||
1782514f DS |
397 | /* Fetch routemap's rule information. */ |
398 | metric = rule; | |
399 | ei = object; | |
d62a17ae | 400 | |
1782514f DS |
401 | /* Set metric out value. */ |
402 | if (!metric->used) | |
403 | return RMAP_OKAY; | |
236e900c | 404 | |
1782514f | 405 | ei->route_map_set.metric = DEFAULT_DEFAULT_METRIC; |
236e900c | 406 | |
1782514f DS |
407 | if (metric->type == metric_increment) |
408 | ei->route_map_set.metric += metric->metric; | |
409 | else if (metric->type == metric_decrement) | |
410 | ei->route_map_set.metric -= metric->metric; | |
411 | else if (metric->type == metric_absolute) | |
412 | ei->route_map_set.metric = metric->metric; | |
413 | ||
414 | if (ei->route_map_set.metric > OSPF_LS_INFINITY) | |
415 | ei->route_map_set.metric = OSPF_LS_INFINITY; | |
7a5e6e46 | 416 | |
d62a17ae | 417 | return RMAP_OKAY; |
718e3744 | 418 | } |
419 | ||
420 | /* set metric compilation. */ | |
d62a17ae | 421 | static void *route_set_metric_compile(const char *arg) |
422 | { | |
6a74c5f9 DS |
423 | struct ospf_metric *metric; |
424 | ||
cf0f13de | 425 | metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*metric)); |
6a74c5f9 | 426 | metric->used = false; |
d62a17ae | 427 | |
7a5e6e46 | 428 | if (all_digit(arg)) |
429 | metric->type = metric_absolute; | |
430 | ||
431 | if (strmatch(arg, "+rtt") || strmatch(arg, "-rtt")) { | |
cf444bcf | 432 | flog_warn(EC_OSPF_SET_METRIC_PLUS, |
45301f8c | 433 | "OSPF does not support 'set metric +rtt / -rtt'"); |
7a5e6e46 | 434 | return metric; |
435 | } | |
436 | ||
437 | if ((arg[0] == '+') && all_digit(arg + 1)) { | |
438 | metric->type = metric_increment; | |
439 | arg++; | |
ed2eb093 | 440 | } |
7a5e6e46 | 441 | |
442 | if ((arg[0] == '-') && all_digit(arg + 1)) { | |
443 | metric->type = metric_decrement; | |
444 | arg++; | |
445 | } | |
446 | ||
6a74c5f9 | 447 | metric->metric = strtoul(arg, NULL, 10); |
7a5e6e46 | 448 | |
449 | if (metric->metric) | |
450 | metric->used = true; | |
d62a17ae | 451 | |
452 | return metric; | |
718e3744 | 453 | } |
454 | ||
455 | /* Free route map's compiled `set metric' value. */ | |
d62a17ae | 456 | static void route_set_metric_free(void *rule) |
718e3744 | 457 | { |
d62a17ae | 458 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 459 | } |
460 | ||
461 | /* Set metric rule structure. */ | |
364deb04 DL |
462 | static const struct route_map_rule_cmd route_set_metric_cmd = { |
463 | "metric", | |
464 | route_set_metric, | |
465 | route_set_metric_compile, | |
d62a17ae | 466 | route_set_metric_free, |
718e3744 | 467 | }; |
468 | ||
469 | /* `set metric-type TYPE' */ | |
470 | /* Set metric-type to attribute. */ | |
b68885f9 | 471 | static enum route_map_cmd_result_t |
1782514f | 472 | route_set_metric_type(void *rule, const struct prefix *prefix, void *object) |
718e3744 | 473 | { |
d7c0a89a | 474 | uint32_t *metric_type; |
d62a17ae | 475 | struct external_info *ei; |
476 | ||
1782514f DS |
477 | /* Fetch routemap's rule information. */ |
478 | metric_type = rule; | |
479 | ei = object; | |
480 | ||
481 | /* Set metric out value. */ | |
482 | ei->route_map_set.metric_type = *metric_type; | |
d62a17ae | 483 | |
d62a17ae | 484 | return RMAP_OKAY; |
718e3744 | 485 | } |
486 | ||
487 | /* set metric-type compilation. */ | |
d62a17ae | 488 | static void *route_set_metric_type_compile(const char *arg) |
718e3744 | 489 | { |
d7c0a89a | 490 | uint32_t *metric_type; |
718e3744 | 491 | |
d7c0a89a | 492 | metric_type = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t)); |
d62a17ae | 493 | if (strcmp(arg, "type-1") == 0) |
494 | *metric_type = EXTERNAL_METRIC_TYPE_1; | |
495 | else if (strcmp(arg, "type-2") == 0) | |
496 | *metric_type = EXTERNAL_METRIC_TYPE_2; | |
718e3744 | 497 | |
d62a17ae | 498 | if (*metric_type == EXTERNAL_METRIC_TYPE_1 |
499 | || *metric_type == EXTERNAL_METRIC_TYPE_2) | |
500 | return metric_type; | |
718e3744 | 501 | |
d62a17ae | 502 | XFREE(MTYPE_ROUTE_MAP_COMPILED, metric_type); |
503 | return NULL; | |
718e3744 | 504 | } |
505 | ||
506 | /* Free route map's compiled `set metric-type' value. */ | |
d62a17ae | 507 | static void route_set_metric_type_free(void *rule) |
718e3744 | 508 | { |
d62a17ae | 509 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
718e3744 | 510 | } |
511 | ||
512 | /* Set metric rule structure. */ | |
364deb04 DL |
513 | static const struct route_map_rule_cmd route_set_metric_type_cmd = { |
514 | "metric-type", | |
515 | route_set_metric_type, | |
516 | route_set_metric_type_compile, | |
d62a17ae | 517 | route_set_metric_type_free, |
718e3744 | 518 | }; |
519 | ||
b68885f9 | 520 | static enum route_map_cmd_result_t |
1782514f | 521 | route_set_tag(void *rule, const struct prefix *prefix, void *object) |
0d9551dc | 522 | { |
d62a17ae | 523 | route_tag_t *tag; |
524 | struct external_info *ei; | |
0d9551dc | 525 | |
1782514f DS |
526 | tag = rule; |
527 | ei = object; | |
0d9551dc | 528 | |
1782514f DS |
529 | /* Set tag value */ |
530 | ei->tag = *tag; | |
0d9551dc | 531 | |
d62a17ae | 532 | return RMAP_OKAY; |
0d9551dc DS |
533 | } |
534 | ||
0d9551dc | 535 | /* Route map commands for tag set. */ |
364deb04 DL |
536 | static const struct route_map_rule_cmd route_set_tag_cmd = { |
537 | "tag", | |
538 | route_set_tag, | |
539 | route_map_rule_tag_compile, | |
d62a17ae | 540 | route_map_rule_tag_free, |
0d9551dc DS |
541 | }; |
542 | ||
a623b526 | 543 | DEFUN_YANG (set_metric_type, |
718e3744 | 544 | set_metric_type_cmd, |
6147e2c6 | 545 | "set metric-type <type-1|type-2>", |
718e3744 | 546 | SET_STR |
547 | "Type of metric for destination routing protocol\n" | |
73ffb25b | 548 | "OSPF[6] external type 1 metric\n" |
549 | "OSPF[6] external type 2 metric\n") | |
718e3744 | 550 | { |
d62a17ae | 551 | char *ext = argv[2]->text; |
a623b526 SP |
552 | |
553 | const char *xpath = | |
554 | "./set-action[action='frr-ospf-route-map:metric-type']"; | |
555 | char xpath_value[XPATH_MAXLEN]; | |
556 | ||
557 | nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); | |
558 | snprintf(xpath_value, sizeof(xpath_value), | |
559 | "%s/rmap-set-action/frr-ospf-route-map:metric-type", xpath); | |
560 | nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ext); | |
561 | return nb_cli_apply_changes(vty, NULL); | |
718e3744 | 562 | } |
563 | ||
a623b526 | 564 | DEFUN_YANG (no_set_metric_type, |
718e3744 | 565 | no_set_metric_type_cmd, |
692b4c65 | 566 | "no set metric-type [<type-1|type-2>]", |
718e3744 | 567 | NO_STR |
568 | SET_STR | |
ff788d08 | 569 | "Type of metric for destination routing protocol\n" |
692b4c65 | 570 | "OSPF[6] external type 1 metric\n" |
ff788d08 | 571 | "OSPF[6] external type 2 metric\n") |
718e3744 | 572 | { |
a623b526 SP |
573 | const char *xpath = |
574 | "./set-action[action='frr-ospf-route-map:metric-type']"; | |
575 | ||
576 | nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); | |
577 | return nb_cli_apply_changes(vty, NULL); | |
0d9551dc DS |
578 | } |
579 | ||
718e3744 | 580 | /* Route-map init */ |
d62a17ae | 581 | void ospf_route_map_init(void) |
718e3744 | 582 | { |
d62a17ae | 583 | route_map_init(); |
584 | ||
585 | route_map_add_hook(ospf_route_map_update); | |
586 | route_map_delete_hook(ospf_route_map_update); | |
587 | route_map_event_hook(ospf_route_map_event); | |
718e3744 | 588 | |
d62a17ae | 589 | route_map_set_metric_hook(generic_set_add); |
590 | route_map_no_set_metric_hook(generic_set_delete); | |
82f97584 | 591 | |
d62a17ae | 592 | route_map_match_ip_next_hop_hook(generic_match_add); |
593 | route_map_no_match_ip_next_hop_hook(generic_match_delete); | |
58b0878a | 594 | |
d62a17ae | 595 | route_map_match_interface_hook(generic_match_add); |
596 | route_map_no_match_interface_hook(generic_match_delete); | |
58b0878a | 597 | |
d62a17ae | 598 | route_map_match_ip_address_hook(generic_match_add); |
599 | route_map_no_match_ip_address_hook(generic_match_delete); | |
82f97584 | 600 | |
d62a17ae | 601 | route_map_match_ip_address_prefix_list_hook(generic_match_add); |
602 | route_map_no_match_ip_address_prefix_list_hook(generic_match_delete); | |
82f97584 | 603 | |
d62a17ae | 604 | route_map_match_ip_next_hop_prefix_list_hook(generic_match_add); |
605 | route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete); | |
82f97584 | 606 | |
b6c0e913 DA |
607 | route_map_match_ip_next_hop_type_hook(generic_match_add); |
608 | route_map_no_match_ip_next_hop_type_hook(generic_match_delete); | |
609 | ||
d62a17ae | 610 | route_map_match_tag_hook(generic_match_add); |
611 | route_map_no_match_tag_hook(generic_match_delete); | |
82f97584 | 612 | |
d62a17ae | 613 | route_map_set_metric_hook(generic_set_add); |
614 | route_map_no_set_metric_hook(generic_set_delete); | |
82f97584 | 615 | |
d62a17ae | 616 | route_map_set_tag_hook(generic_set_add); |
617 | route_map_no_set_tag_hook(generic_set_delete); | |
82f97584 | 618 | |
d62a17ae | 619 | route_map_install_match(&route_match_ip_nexthop_cmd); |
620 | route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd); | |
621 | route_map_install_match(&route_match_ip_address_cmd); | |
622 | route_map_install_match(&route_match_ip_address_prefix_list_cmd); | |
b6c0e913 | 623 | route_map_install_match(&route_match_ip_next_hop_type_cmd); |
d62a17ae | 624 | route_map_install_match(&route_match_interface_cmd); |
625 | route_map_install_match(&route_match_tag_cmd); | |
718e3744 | 626 | |
d62a17ae | 627 | route_map_install_set(&route_set_metric_cmd); |
628 | route_map_install_set(&route_set_metric_type_cmd); | |
629 | route_map_install_set(&route_set_tag_cmd); | |
718e3744 | 630 | |
d62a17ae | 631 | install_element(RMAP_NODE, &set_metric_type_cmd); |
632 | install_element(RMAP_NODE, &no_set_metric_type_cmd); | |
718e3744 | 633 | } |