blob: 3e0ab047eddef9a7b4a1796f7291839d272d2525 [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
Christian Frankeacf98652015-11-12 14:24:22 +01002 * IS-IS Rout(e)ing protocol - isis_routemap.c
jardineb5d44e2003-12-23 08:09:43 +00003 *
Christian Frankeacf98652015-11-12 14:24:22 +01004 * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
jardineb5d44e2003-12-23 08:09:43 +00005 *
6 * This program is free software; you can redistribute it and/or modify it
Christian Frankeacf98652015-11-12 14:24:22 +01007 * under the terms of the GNU General Public License as published by the Free
jardineb5d44e2003-12-23 08:09:43 +00008 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
Christian Frankeacf98652015-11-12 14:24:22 +010020
jardineb5d44e2003-12-23 08:09:43 +000021#include <zebra.h>
jardineb5d44e2003-12-23 08:09:43 +000022
Christian Frankeacf98652015-11-12 14:24:22 +010023#include "command.h"
24#include "filter.h"
25#include "hash.h"
26#include "if.h"
jardineb5d44e2003-12-23 08:09:43 +000027#include "linklist.h"
jardineb5d44e2003-12-23 08:09:43 +000028#include "log.h"
29#include "memory.h"
30#include "prefix.h"
Christian Frankeacf98652015-11-12 14:24:22 +010031#include "plist.h"
jardineb5d44e2003-12-23 08:09:43 +000032#include "routemap.h"
Christian Frankeacf98652015-11-12 14:24:22 +010033#include "table.h"
34#include "thread.h"
35#include "vty.h"
jardineb5d44e2003-12-23 08:09:43 +000036
37#include "isis_constants.h"
38#include "isis_common.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070039#include "isis_flags.h"
jardineb5d44e2003-12-23 08:09:43 +000040#include "dict.h"
41#include "isisd.h"
42#include "isis_misc.h"
43#include "isis_adjacency.h"
44#include "isis_circuit.h"
45#include "isis_tlv.h"
46#include "isis_pdu.h"
47#include "isis_lsp.h"
48#include "isis_spf.h"
49#include "isis_route.h"
50#include "isis_zebra.h"
Christian Frankeacf98652015-11-12 14:24:22 +010051#include "isis_routemap.h"
jardineb5d44e2003-12-23 08:09:43 +000052
Christian Frankeacf98652015-11-12 14:24:22 +010053static route_map_result_t
54route_match_ip_address(void *rule, struct prefix *prefix,
55 route_map_object_t type, void *object)
jardineb5d44e2003-12-23 08:09:43 +000056{
Christian Frankeacf98652015-11-12 14:24:22 +010057 struct access_list *alist;
hassof390d2c2004-09-10 20:48:21 +000058
Christian Frankeacf98652015-11-12 14:24:22 +010059 if (type != RMAP_ISIS)
60 return RMAP_NOMATCH;
hassof390d2c2004-09-10 20:48:21 +000061
Christian Frankeacf98652015-11-12 14:24:22 +010062 alist = access_list_lookup(AFI_IP, (char*)rule);
63 if (access_list_apply(alist, prefix) != FILTER_DENY)
64 return RMAP_MATCH;
65
66 return RMAP_NOMATCH;
jardineb5d44e2003-12-23 08:09:43 +000067}
68
Christian Frankeacf98652015-11-12 14:24:22 +010069static void *
70route_match_ip_address_compile(const char *arg)
jardineb5d44e2003-12-23 08:09:43 +000071{
Christian Frankeacf98652015-11-12 14:24:22 +010072 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
jardineb5d44e2003-12-23 08:09:43 +000073}
74
Christian Frankeacf98652015-11-12 14:24:22 +010075static void
76route_match_ip_address_free(void *rule)
jardineb5d44e2003-12-23 08:09:43 +000077{
Christian Frankeacf98652015-11-12 14:24:22 +010078 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
79}
hassof390d2c2004-09-10 20:48:21 +000080
Christian Frankeacf98652015-11-12 14:24:22 +010081static struct route_map_rule_cmd route_match_ip_address_cmd =
82{
83 "ip address",
84 route_match_ip_address,
85 route_match_ip_address_compile,
86 route_match_ip_address_free
87};
88
89/* ------------------------------------------------------------*/
90
91static route_map_result_t
92route_match_ip_address_prefix_list(void *rule, struct prefix *prefix,
93 route_map_object_t type, void *object)
94{
95 struct prefix_list *plist;
96
97 if (type != RMAP_ISIS)
98 return RMAP_NOMATCH;
99
100 plist = prefix_list_lookup(AFI_IP, (char*)rule);
101 if (prefix_list_apply(plist, prefix) != PREFIX_DENY)
102 return RMAP_MATCH;
103
104 return RMAP_NOMATCH;
105}
106
107static void *
108route_match_ip_address_prefix_list_compile(const char *arg)
109{
110 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
111}
112
113static void
114route_match_ip_address_prefix_list_free (void *rule)
115{
116 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
117}
118
119struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
120{
121 "ip address prefix-list",
122 route_match_ip_address_prefix_list,
123 route_match_ip_address_prefix_list_compile,
124 route_match_ip_address_prefix_list_free
125};
126
127/* ------------------------------------------------------------*/
128
129static route_map_result_t
130route_match_ipv6_address(void *rule, struct prefix *prefix,
131 route_map_object_t type, void *object)
132{
133 struct access_list *alist;
134
135 if (type != RMAP_ISIS)
136 return RMAP_NOMATCH;
137
138 alist = access_list_lookup(AFI_IP6, (char*)rule);
139 if (access_list_apply(alist, prefix) != FILTER_DENY)
140 return RMAP_MATCH;
141
142 return RMAP_NOMATCH;
143}
144
145static void *
146route_match_ipv6_address_compile(const char *arg)
147{
148 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
149}
150
151static void
152route_match_ipv6_address_free(void *rule)
153{
154 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
155}
156
157static struct route_map_rule_cmd route_match_ipv6_address_cmd =
158{
159 "ipv6 address",
160 route_match_ipv6_address,
161 route_match_ipv6_address_compile,
162 route_match_ipv6_address_free
163};
164
165/* ------------------------------------------------------------*/
166
167static route_map_result_t
168route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix,
169 route_map_object_t type, void *object)
170{
171 struct prefix_list *plist;
172
173 if (type != RMAP_ISIS)
174 return RMAP_NOMATCH;
175
176 plist = prefix_list_lookup(AFI_IP6, (char*)rule);
177 if (prefix_list_apply(plist, prefix) != PREFIX_DENY)
178 return RMAP_MATCH;
179
180 return RMAP_NOMATCH;
181}
182
183static void *
184route_match_ipv6_address_prefix_list_compile(const char *arg)
185{
186 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
187}
188
189static void
190route_match_ipv6_address_prefix_list_free (void *rule)
191{
192 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
193}
194
195struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd =
196{
197 "ipv6 address prefix-list",
198 route_match_ipv6_address_prefix_list,
199 route_match_ipv6_address_prefix_list_compile,
200 route_match_ipv6_address_prefix_list_free
201};
202
203/* ------------------------------------------------------------*/
204
205static route_map_result_t
206route_set_metric(void *rule, struct prefix *prefix,
207 route_map_object_t type, void *object)
208{
209 uint32_t *metric;
210 struct isis_ext_info *info;
211
212 if (type == RMAP_ISIS)
213 {
214 metric = rule;
215 info = object;
216
217 info->metric = *metric;
218 }
219 return RMAP_OKAY;
220}
221
222static void *
223route_set_metric_compile(const char *arg)
224{
225 unsigned long metric;
226 char *endp;
227 uint32_t *ret;
228
229 metric = strtoul(arg, &endp, 10);
230 if (arg[0] == '\0' || *endp != '\0' || metric > MAX_WIDE_PATH_METRIC)
231 return NULL;
232
233 ret = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(ret));
234 *ret = metric;
235
236 return ret;
237}
238
239static void
240route_set_metric_free(void *rule)
241{
242 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
243}
244
245static struct route_map_rule_cmd route_set_metric_cmd =
246{
247 "metric",
248 route_set_metric,
249 route_set_metric_compile,
250 route_set_metric_free
251};
252
253/* ------------------------------------------------------------*/
254
255static int
256isis_route_match_add(struct vty *vty, struct route_map_index *index,
257 const char *command, const char *arg)
258{
259 int ret;
260
261 ret = route_map_add_match (index, command, arg);
262 if (ret)
263 {
264 switch (ret)
265 {
266 case RMAP_RULE_MISSING:
267 vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
268 return CMD_WARNING;
269 case RMAP_COMPILE_ERROR:
270 vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
271 return CMD_WARNING;
272 }
273 }
274 return CMD_SUCCESS;
275}
276
277static int
278isis_route_match_delete(struct vty *vty, struct route_map_index *index,
279 const char *command, const char *arg)
280{
281 int ret;
282
283 ret = route_map_delete_match (index, command, arg);
284 if (ret)
285 {
286 switch (ret)
287 {
288 case RMAP_RULE_MISSING:
289 vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
290 return CMD_WARNING;
291 case RMAP_COMPILE_ERROR:
292 vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
293 return CMD_WARNING;
294 }
295 }
296 return CMD_SUCCESS;
297}
298
299static int
300isis_route_set_add(struct vty *vty, struct route_map_index *index,
301 const char *command, const char *arg)
302{
303 int ret;
304
305 ret = route_map_add_set(index, command, arg);
306 if (ret)
307 {
308 switch (ret)
309 {
310 case RMAP_RULE_MISSING:
311 vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
312 return CMD_WARNING;
313 case RMAP_COMPILE_ERROR:
314 vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
315 return CMD_WARNING;
316 }
317 }
318
319 return CMD_SUCCESS;
320}
321
322static int
323isis_route_set_delete (struct vty *vty, struct route_map_index *index,
324 const char *command, const char *arg)
325{
326 int ret;
327
328 ret = route_map_delete_set (index, command, arg);
329 if (ret)
330 {
331 switch (ret)
332 {
333 case RMAP_RULE_MISSING:
334 vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
335 return CMD_WARNING;
336 case RMAP_COMPILE_ERROR:
337 vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
338 return CMD_WARNING;
339 }
340 }
341
342 return CMD_SUCCESS;
343}
344
345/* ------------------------------------------------------------*/
346
347DEFUN(match_ip_address,
348 match_ip_address_cmd,
349 "match ip address (<1-199>|<1300-2699>|WORD)",
350 MATCH_STR
351 IP_STR
352 "Match address of route\n"
353 "IP access-list number\n"
354 "IP access-list number (expanded range)\n"
355 "IP Access-list name\n")
356{
357 return isis_route_match_add(vty, vty->index, "ip address", argv[0]);
358}
359
360DEFUN(no_match_ip_address,
361 no_match_ip_address_val_cmd,
362 "no match ip address (<1-199>|<1300-2699>|WORD)",
363 NO_STR
364 MATCH_STR
365 IP_STR
366 "Match address of route\n"
367 "IP access-list number\n"
368 "IP access-list number (expanded range)\n"
369 "IP Access-list name\n")
370{
371 if (argc == 0)
372 return isis_route_match_delete(vty, vty->index, "ip address", NULL);
373 return isis_route_match_delete(vty, vty->index, "ip address", argv[0]);
374}
375
376ALIAS(no_match_ip_address,
377 no_match_ip_address_cmd,
378 "no match ip address",
379 NO_STR
380 MATCH_STR
381 IP_STR
382 "Match address of route\n"
383);
384
385/* ------------------------------------------------------------*/
386
387DEFUN(match_ip_address_prefix_list,
388 match_ip_address_prefix_list_cmd,
389 "match ip address prefix-list WORD",
390 MATCH_STR
391 IP_STR
392 "Match address of route\n"
393 "Match entries of prefix-lists\n"
394 "IP prefix-list name\n")
395{
396 return isis_route_match_add(vty, vty->index, "ip address prefix-list", argv[0]);
397}
398
399DEFUN(no_match_ip_address_prefix_list,
400 no_match_ip_address_prefix_list_cmd,
401 "no match ip address prefix-list",
402 NO_STR
403 MATCH_STR
404 IP_STR
405 "Match address of route\n"
406 "Match entries of prefix-lists\n")
407{
408 if (argc == 0)
409 return isis_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
410 return isis_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
411}
412
413ALIAS(no_match_ip_address_prefix_list,
414 no_match_ip_address_prefix_list_val_cmd,
415 "no match ip address prefix-list WORD",
416 NO_STR
417 MATCH_STR
418 IP_STR
419 "Match address of route\n"
420 "Match entries of prefix-lists\n"
421 "IP prefix-list name\n"
422);
423
424/* ------------------------------------------------------------*/
425
426DEFUN(match_ipv6_address,
427 match_ipv6_address_cmd,
428 "match ipv6 address WORD",
429 MATCH_STR
430 IPV6_STR
431 "Match IPv6 address of route\n"
432 "IPv6 access-list name\n")
433{
434 return isis_route_match_add(vty, vty->index, "ipv6 address", argv[0]);
435}
436
437DEFUN(no_match_ipv6_address,
438 no_match_ipv6_address_val_cmd,
439 "no match ipv6 address WORD",
440 NO_STR
441 MATCH_STR
442 IPV6_STR
443 "Match IPv6 address of route\n"
444 "IPv6 access-list name\n")
445{
446 if (argc == 0)
447 return isis_route_match_delete(vty, vty->index, "ipv6 address", NULL);
448 return isis_route_match_delete(vty, vty->index, "ipv6 address", argv[0]);
449}
450
451ALIAS(no_match_ipv6_address,
452 no_match_ipv6_address_cmd,
453 "no match ipv6 address",
454 NO_STR
455 MATCH_STR
456 IPV6_STR
457 "Match IPv6 address of route\n"
458);
459
460/* ------------------------------------------------------------*/
461
462DEFUN(match_ipv6_address_prefix_list,
463 match_ipv6_address_prefix_list_cmd,
464 "match ipv6 address prefix-list WORD",
465 MATCH_STR
466 IPV6_STR
467 "Match address of route\n"
468 "Match entries of prefix-lists\n"
469 "IP prefix-list name\n")
470{
471 return isis_route_match_add(vty, vty->index, "ipv6 address prefix-list", argv[0]);
472}
473
474DEFUN(no_match_ipv6_address_prefix_list,
475 no_match_ipv6_address_prefix_list_cmd,
476 "no match ipv6 address prefix-list",
477 NO_STR
478 MATCH_STR
479 IPV6_STR
480 "Match address of route\n"
481 "Match entries of prefix-lists\n")
482{
483 if (argc == 0)
484 return isis_route_match_delete (vty, vty->index, "ipv6 address prefix-list", NULL);
485 return isis_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]);
486}
487
488ALIAS(no_match_ipv6_address_prefix_list,
489 no_match_ipv6_address_prefix_list_val_cmd,
490 "no match ipv6 address prefix-list WORD",
491 NO_STR
492 MATCH_STR
493 IPV6_STR
494 "Match address of route\n"
495 "Match entries of prefix-lists\n"
496 "IP prefix-list name\n"
497);
498
499/* ------------------------------------------------------------*/
500
501/* set metric already exists e.g. in the ospf routemap. vtysh doesn't cope well with different
502 * commands at the same node, therefore add set metric with the same 32-bit range as ospf and
503 * verify that the input is a valid isis metric */
504DEFUN(set_metric,
505 set_metric_cmd,
506 "set metric <0-4294967295>",
507 SET_STR
508 "Metric vale for destination routing protocol\n"
509 "Metric value\n")
510{
511 return isis_route_set_add(vty, vty->index, "metric", argv[0]);
512}
513
514DEFUN(no_set_metric,
515 no_set_metric_val_cmd,
516 "no set metric <0-4294967295>",
517 NO_STR
518 SET_STR
519 "Metric value for destination routing protocol\n"
520 "Metric value\n")
521{
522 if (argc == 0)
523 return isis_route_set_delete(vty, vty->index, "metric", NULL);
524 return isis_route_set_delete(vty, vty->index, "metric", argv[0]);
525}
526
527ALIAS(no_set_metric,
528 no_set_metric_cmd,
529 "no set metric",
530 NO_STR
531 SET_STR
532 "Metric vale for destination routing protocol\n"
533);
534
535void
536isis_route_map_init(void)
537{
538 route_map_init();
539 route_map_init_vty();
540
541 route_map_install_match(&route_match_ip_address_cmd);
542 install_element(RMAP_NODE, &match_ip_address_cmd);
543 install_element(RMAP_NODE, &no_match_ip_address_val_cmd);
544 install_element(RMAP_NODE, &no_match_ip_address_cmd);
545
546 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
547 install_element(RMAP_NODE, &match_ip_address_prefix_list_cmd);
548 install_element(RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
549 install_element(RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
550
551 route_map_install_match(&route_match_ipv6_address_cmd);
552 install_element(RMAP_NODE, &match_ipv6_address_cmd);
553 install_element(RMAP_NODE, &no_match_ipv6_address_val_cmd);
554 install_element(RMAP_NODE, &no_match_ipv6_address_cmd);
555
556 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
557 install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
558 install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_val_cmd);
559 install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
560
561 route_map_install_set(&route_set_metric_cmd);
562 install_element(RMAP_NODE, &set_metric_cmd);
563 install_element(RMAP_NODE, &no_set_metric_val_cmd);
564 install_element(RMAP_NODE, &no_set_metric_cmd);
jardineb5d44e2003-12-23 08:09:43 +0000565}