📄 routemap.c
字号:
}/* Add route-map set statement to the route map. */introute_map_add_set (struct route_map_index *index, char *set_name, char *set_arg){ struct route_map_rule *rule; struct route_map_rule *next; struct route_map_rule_cmd *cmd; void *compile; int replaced = 0; cmd = route_map_lookup_set (set_name); if (cmd == NULL) return RMAP_RULE_MISSING; /* Next call compile function for this match statement. */ if (cmd->func_compile) { compile= (*cmd->func_compile)(set_arg); if (compile == NULL) return RMAP_COMPILE_ERROR; } else compile = NULL; /* Add by WJL. if old set command of same kind exist, delete it first to ensure only one set command of same kind exist under a route_map_index. */ for (rule = index->set_list.head; rule; rule = next) { next = rule->next; if (rule->cmd == cmd) { route_map_rule_delete (&index->set_list, rule); replaced = 1; } } /* Add new route map match rule. */ rule = route_map_rule_new (); rule->cmd = cmd; rule->value = compile; if (set_arg) rule->rule_str = XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR, set_arg); else rule->rule_str = NULL; /* Add new route match rule to linked list. */ route_map_rule_add (&index->set_list, rule); /* Execute event hook. */ if (route_map_master.event_hook) (*route_map_master.event_hook) (replaced ? RMAP_EVENT_SET_REPLACED: RMAP_EVENT_SET_ADDED, index->map->name); return 0;}/* Delete route map set rule. */introute_map_delete_set (struct route_map_index *index, char *set_name, char *set_arg){ struct route_map_rule *rule; struct route_map_rule_cmd *cmd; cmd = route_map_lookup_set (set_name); if (cmd == NULL) return 1; for (rule = index->set_list.head; rule; rule = rule->next) if ((rule->cmd == cmd) && (rulecmp (rule->rule_str, set_arg) == 0 || set_arg == NULL)) { route_map_rule_delete (&index->set_list, rule); /* Execute event hook. */ if (route_map_master.event_hook) (*route_map_master.event_hook) (RMAP_EVENT_SET_DELETED, index->map->name); return 0; } /* Can't find matched rule. */ return 1;}/* Apply route map's each index to the object. The matrix for a route-map looks like this: (note, this includes the description for the "NEXT" and "GOTO" frobs now Match | No Match | permit a | c | ------------------+--------------- | deny b | d | a) Apply Set statements, accept route If NEXT is specified, goto NEXT statement If GOTO is specified, goto the first clause where pref > nextpref If nothing is specified, do as Cisco and finish b) If NEXT is specified, goto NEXT statement If nothing is specified, finally will be denied by route-map. c) & d) Goto Next index If we get no matches after we've processed all updates, then the route is dropped too. Some notes on the new "NEXT" and "GOTO" on-match next - If this clause is matched, then the set statements are executed and then we drop through to the next clause on-match goto n - If this clause is matched, then the set statments are executed and then we goto the nth clause, or the first clause greater than this. In order to ensure route-maps *always* exit, you cannot jump backwards. Sorry ;) We need to make sure our route-map processing matches the above*/route_map_result_troute_map_apply_index (struct route_map_index *index, struct prefix *prefix, route_map_object_t type, void *object){ int ret = 0; struct route_map_rule *match; struct route_map_rule *set; /* Check all match rule and if there is no match rule, go to the set statement. */ if (! index->match_list.head) ret = RMAP_MATCH; else { for (match = index->match_list.head; match; match = match->next) { /* Try each match statement in turn, If any return RMAP_MATCH, go direct to set statement, otherwise, walk to next match statement. */ ret = (*match->cmd->func_apply)(match->value, prefix, type, object); if (ret == RMAP_MATCH) break; } } /* If end of match statement, still can't get any RMAP_MATCH return, just return to next rout-map statement. */ if (ret != RMAP_MATCH) return ret; /* We get here if all match statements matched From the matrix above, if this is PERMIT we go on and apply the SET functions. If we're deny, we return indicating we matched a deny */ /* Apply set statement to the object. */ if (index->type == RMAP_PERMIT) { for (set = index->set_list.head; set; set = set->next) ret = (*set->cmd->func_apply)(set->value, prefix, type, object); return RMAP_MATCH; } else { return RMAP_DENYMATCH; } /* Should not get here! */ return RMAP_MATCH;}/* Apply route map to the object. */route_map_result_troute_map_apply (struct route_map *map, struct prefix *prefix, route_map_object_t type, void *object){ int ret = 0; struct route_map_index *index; if (map == NULL) return RMAP_DENYMATCH; for (index = map->head; index; index = index->next) { /* Apply this index. End here if we get a RM_NOMATCH */ ret = route_map_apply_index (index, prefix, type, object); if (ret == RMAP_MATCH || ret == RMAP_DENYMATCH) return ret; if (ret != RMAP_NOMATCH) { /* We now have to handle the NEXT and GOTO clauses */ if(index->exitpolicy == RMAP_EXIT) return ret; if(index->exitpolicy == RMAP_GOTO) { /* Find the next clause to jump to */ struct route_map_index *next; next = index->next; while (next && next->pref < index->nextpref) { index = next; next = next->next; } if (next == NULL) { /* No clauses match! */ return ret; } } /* Otherwise, we fall through as it was a NEXT */ } } /* Finally route-map does not match at all. */ return RMAP_DENYMATCH;}voidroute_map_add_hook (void (*func) (char *)){ route_map_master.add_hook = func;}voidroute_map_delete_hook (void (*func) (char *)){ route_map_master.delete_hook = func;}voidroute_map_event_hook (void (*func) (route_map_event_t, char *)){ route_map_master.event_hook = func;}voidroute_map_init (){ /* Make vector for match and set. */ route_match_vec = vector_init (1); route_set_vec = vector_init (1);}/* VTY related functions. */DEFUN (route_map, route_map_cmd, "route-map WORD (deny|permit) <1-65535>", "Create route-map or enter route-map command mode\n" "Route map tag\n" "Route map denies set operations\n" "Route map permits set operations\n" "Sequence to insert to/delete from existing route-map entry\n"){ int permit; unsigned long pref; struct route_map *map; struct route_map_index *index; char *endptr = NULL; /* Permit check. */ if (strncmp (argv[1], "permit", strlen (argv[1])) == 0) permit = RMAP_PERMIT; else if (strncmp (argv[1], "deny", strlen (argv[1])) == 0) permit = RMAP_DENY; else { vty_out (vty, "the third field must be [permit|deny]%s", VTY_NEWLINE); return CMD_WARNING; } /* Preference check. */ pref = strtoul (argv[2], &endptr, 10); if (pref == ULONG_MAX || *endptr != '\0') { vty_out (vty, "the fourth field must be positive integer%s", VTY_NEWLINE); return CMD_WARNING; } if (pref == 0 || pref > 65535) { vty_out (vty, "the fourth field must be <1-65535>%s", VTY_NEWLINE); return CMD_WARNING; } /* Get route map. */ map = route_map_get (argv[0]); index = route_map_index_get (map, permit, pref); vty->index = index; vty->node = RMAP_NODE; return CMD_SUCCESS;}DEFUN (no_route_map_all, no_route_map_all_cmd, "no route-map WORD", NO_STR "Create route-map or enter route-map command mode\n" "Route map tag\n"){ struct route_map *map; map = route_map_lookup_by_name (argv[0]); if (map == NULL) { vty_out (vty, "%% Could not find route-map %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; } route_map_delete (map); return CMD_SUCCESS;}DEFUN (no_route_map, no_route_map_cmd, "no route-map WORD (deny|permit) <1-65535>", NO_STR "Create route-map or enter route-map command mode\n" "Route map tag\n" "Route map denies set operations\n" "Route map permits set operations\n" "Sequence to insert to/delete from existing route-map entry\n"){ int permit; unsigned long pref; struct route_map *map; struct route_map_index *index; char *endptr = NULL; /* Permit check. */ if (strncmp (argv[1], "permit", strlen (argv[1])) == 0) permit = RMAP_PERMIT; else if (strncmp (argv[1], "deny", strlen (argv[1])) == 0) permit = RMAP_DENY; else { vty_out (vty, "the third field must be [permit|deny]%s", VTY_NEWLINE); return CMD_WARNING; } /* Preference. */ pref = strtoul (argv[2], &endptr, 10); if (pref == ULONG_MAX || *endptr != '\0') { vty_out (vty, "the fourth field must be positive integer%s", VTY_NEWLINE); return CMD_WARNING; } if (pref == 0 || pref > 65535) { vty_out (vty, "the fourth field must be <1-65535>%s", VTY_NEWLINE); return CMD_WARNING; } /* Existence check. */ map = route_map_lookup_by_name (argv[0]); if (map == NULL) { vty_out (vty, "%% Could not find route-map %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; } /* Lookup route map index. */ index = route_map_index_lookup (map, permit, pref); if (index == NULL) { vty_out (vty, "%% Could not find route-map entry %s %s%s", argv[0], argv[2], VTY_NEWLINE); return CMD_WARNING; } /* Delete index from route map. */ route_map_index_delete (index, 1); /* If this route rule is the last one, delete route map itself. */ if (route_map_empty (map)) route_map_delete (map); return CMD_SUCCESS;}DEFUN (rmap_onmatch_next, rmap_onmatch_next_cmd, "on-match next", "Exit policy on matches\n" "Next clause\n"){ struct route_map_index *index; index = vty->index; if (index) index->exitpolicy = RMAP_NEXT; return CMD_SUCCESS;}DEFUN (no_rmap_onmatch_next, no_rmap_onmatch_next_cmd, "no on-match next", NO_STR "Exit policy on matches\n" "Next clause\n"){ struct route_map_index *index; index = vty->index; if (index) index->exitpolicy = RMAP_EXIT; return CMD_SUCCESS;}DEFUN (rmap_onmatch_goto, rmap_onmatch_goto_cmd, "on-match goto <1-65535>", "Exit policy on matches\n" "Goto Clause number\n" "Number\n"){ struct route_map_index *index; int d = 0; if (argv[0]) d = atoi(argv[0]); index = vty->index; if (index) { if (d <= index->pref) { /* Can't allow you to do that, Dave */ vty_out (vty, "can't jump backwards in route-maps%s", VTY_NEWLINE); return CMD_WARNING; } else { index->exitpolicy = RMAP_GOTO; index->nextpref = d; } } return CMD_SUCCESS;}DEFUN (no_rmap_onmatch_goto, no_rmap_onmatch_goto_cmd, "no on-match goto", NO_STR "Exit policy on matches\n" "Next clause\n"){ struct route_map_index *index; index = vty->index; if (index) index->exitpolicy = RMAP_EXIT; return CMD_SUCCESS;}/* Configuration write function. */introute_map_config_write (struct vty *vty){ struct route_map *map; struct route_map_index *index; struct route_map_rule *rule; int first = 1; int write = 0; for (map = route_map_master.head; map; map = map->next) for (index = map->head; index; index = index->next) { if (!first) vty_out (vty, "!%s", VTY_NEWLINE); else first = 0; vty_out (vty, "route-map %s %s %d%s", map->name, route_map_type_str (index->type), index->pref, VTY_NEWLINE); for (rule = index->match_list.head; rule; rule = rule->next) vty_out (vty, " match %s %s%s", rule->cmd->str, rule->rule_str ? rule->rule_str : "", VTY_NEWLINE); for (rule = index->set_list.head; rule; rule = rule->next) vty_out (vty, " set %s %s%s", rule->cmd->str, rule->rule_str ? rule->rule_str : "", VTY_NEWLINE); if (index->exitpolicy == RMAP_GOTO) vty_out (vty, " on-match goto %d%s", index->nextpref, VTY_NEWLINE); if (index->exitpolicy == RMAP_NEXT) vty_out (vty," on-match next%s", VTY_NEWLINE); write++; } return write;}/* Route map node structure. */struct cmd_node rmap_node ={ RMAP_NODE, "%s(config-route-map)# ", 1};/* Initialization of route map vector. */voidroute_map_init_vty (){ /* Install route map top node. */ install_node (&rmap_node, route_map_config_write); /* Install route map commands. */ install_default (RMAP_NODE); install_element (CONFIG_NODE, &route_map_cmd); install_element (CONFIG_NODE, &no_route_map_cmd); install_element (CONFIG_NODE, &no_route_map_all_cmd); /* Install the on-match stuff */ install_element (RMAP_NODE, &route_map_cmd); install_element (RMAP_NODE, &rmap_onmatch_next_cmd); install_element (RMAP_NODE, &no_rmap_onmatch_next_cmd); install_element (RMAP_NODE, &rmap_onmatch_goto_cmd); install_element (RMAP_NODE, &no_rmap_onmatch_goto_cmd);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -