diff options
author | Chris Hall <chris.hall@highwayman.com> | 2010-10-29 13:35:10 +0100 |
---|---|---|
committer | Chris Hall <chris.hall@highwayman.com> | 2010-10-29 13:52:40 +0100 |
commit | 1793e2518564d42a4d708d2a788821f12e0f9b07 (patch) | |
tree | 95a73a03e84123cfce79b349a9e969b6d0ff8e94 | |
parent | 7dce56f42593e60beb0c0403167e6ab1507f12a1 (diff) | |
download | quagga-1793e2518564d42a4d708d2a788821f12e0f9b07.tar.bz2 quagga-1793e2518564d42a4d708d2a788821f12e0f9b07.tar.xz |
Make routemap sequence numbers 32-bit
Standard Cisco routemap sequence numbers are 1..65535, and Quagga
has followed that. This change extends the range to 4,294,967,295.
Also fixes bug in prefix-list handling for IPv6 /32 prefixes.
-rw-r--r-- | lib/plist.c | 75 | ||||
-rw-r--r-- | lib/routemap.c | 132 | ||||
-rw-r--r-- | lib/routemap.h | 17 |
3 files changed, 144 insertions, 80 deletions
diff --git a/lib/plist.c b/lib/plist.c index 85ff35f8..7cbc49bc 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -180,7 +180,7 @@ prefix_max_length(afi_t afi) return IPV6_MAX_BITLEN ; #endif default: - assert(0) ; /* Should not get here ! */ + zabort("invalid address family") ; return 0 ; } ; } ; @@ -416,8 +416,9 @@ prefix_list_apply (struct prefix_list *plist, void *object) for (VECTOR_ITEMS(&plist->list, pe, i)) { ++pe->refcnt ; - if ((((pe->prefix.u.prefix4.s_addr ^ ip) & pe->mask) == 0) - && (plen >= pe->ge) && (plen <= pe->le)) + if ((plen < pe->ge) || (plen > pe->le)) + continue ; + if (((pe->prefix.u.prefix4.s_addr ^ ip) & pe->mask) == 0) { ++pe->hitcnt; return pe->type ; @@ -433,19 +434,20 @@ prefix_list_apply (struct prefix_list *plist, void *object) #endif for (VECTOR_ITEMS(&plist->list, pe, i)) { - int l = pe->last ; - int j ; + int j, l ; ++pe->refcnt ; + if ((plen < pe->ge) || (plen > pe->le)) + continue ; #ifdef s6_addr32 pep = pe->prefix.u.prefix6.s6_addr32 ; #else pep = pe->prefix.u.prefix6.s6_addr ; #endif + l = pe->last ; for (j = 0 ; j < l ; j++) if (pep[j] != pp[j]) goto NEXT ; - if ((((pep[l] ^ pp[l]) & pe->mask) == 0) - && (plen >= pe->ge) && (plen <= pe->le)) + if (((pep[l] ^ pp[l]) & pe->mask) == 0) { ++pe->hitcnt; return pe->type ; @@ -455,7 +457,7 @@ prefix_list_apply (struct prefix_list *plist, void *object) break ; default: - assert(0) ; + zabort("invalid address family") ; } ; return PREFIX_DENY; @@ -491,7 +493,7 @@ prefix_list_new(struct prefix_master* pm, struct symbol* sym, afi_t afi) break ; #endif default: - assert(0) ; /* Should not get here ! */ + zabort("invalid address family") ; } ; symbol_set_value(sym, new) ; @@ -837,7 +839,7 @@ prefix_list_entry_insert(struct prefix_list *plist, vector_index i, ic ; int ret, retc ; u_int32_t mask ; - int pl ; + int pl, sh ; /* See if we have an entry like this one, if we do: * @@ -916,26 +918,63 @@ prefix_list_entry_insert(struct prefix_list *plist, /* Now we can set the value of the entry. */ *pe = *temp ; - /* Set mask and last ready to apply the filter. */ - /* Note: if we don't have s6_addr32, we must handle IPv6 byte-wise ! */ + /* Set mask and last ready to apply the filter. + * + * pl sh mask last + * 0 0 0x00000000 0 case sh == 0 && pl == 0 + * 1 1 0x80000000 0 + * .. .. . + * 31 31 0xFFFFFFFE 0 + * 32 0 0xFFFFFFFF 0 case sh == 0 + * 33 1 0x80000000 1 + * .. .. . + * 64 0 0xFFFFFFFF 1 case sh == 0 + * 65 1 0x80000000 2 + * .. .. . + * 128 0 0xFFFFFFFF 3 case sh == 0 + * + * Note: if we don't have s6_addr32, we must handle IPv6 byte-wise ! + */ pl = pe->prefix.prefixlen ; - mask = htonl((0xFFFFFFFF >> (pl & 0x1F)) ^ 0xFFFFFFFF) ; + + sh = pl & 0x1F ; + if (sh == 0) + mask = (pl == 0) ? 0x00000000 : 0xFFFFFFFF ; + else + mask = (0xFFFFFFFF >> sh) ^ 0xFFFFFFFF ; + switch (plist->afi) { case AFI_IP: - pe->mask = mask ; + pe->mask = htonl(mask) ; + pe->last = 0 ; break ; + case AFI_IP6: #ifdef s6_addr32 - pe->mask = mask ; + pe->mask = htonl(mask) ; pe->last = (pl == 0) ? 0 : (pl - 1) >> 5 ; #else - pe->mask = (0xFF >> (pl & 0x07)) ^ 0xFF ; + /* Need to shift 32 bit mask to 8 bit mask + * + * For pl == 0 mask == 0, otherwise: + * + * (pl - 1) & 0x18 -> 0 for pl = 1.. 8, 33..40, 65..72, 97..104 + * 8 for pl = 9..16, etc + * (0x10) 16 for pl = 17..24, etc + * (0x18) 24 for pl = 25..32, etc + * + * So need to shift down by 24 - that, and then mask to byte. + */ + if (pl != 0) + mask >>= (24 - ((pl - 1) & 0x18)) ; + pe->mask = mask & 0xFF ; pe->last = (pl == 0) ? 0 : (pl - 1) >> 3 ; #endif break ; + default: - assert(0) ; + zabort("invalid address family") ; } ; /* Run hook function. */ @@ -1017,7 +1056,7 @@ prefix_afi_name_str(afi_t afi) return "ipv6" ; #endif default: - assert(0) ; /* Should not get here ! */ + zabort("invalid address family") ; return "?" ; } ; } ; diff --git a/lib/routemap.c b/lib/routemap.c index b142e99c..b452530d 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -212,9 +212,10 @@ vty_show_route_map_entry (struct vty *vty, struct route_map *map) for (index = map->head; index; index = index->next) { - vty_out (vty, "route-map %s, %s, sequence %d%s", + vty_out (vty, "route-map %s, %s, sequence %lu%s", map->name, route_map_type_str (index->type), - index->pref, VTY_NEWLINE); + (unsigned long)index->seq, VTY_NEWLINE); + confirm(sizeof(index->seq) <= sizeof(unsigned long)) ; /* Description */ if (index->description) @@ -239,12 +240,25 @@ vty_show_route_map_entry (struct vty *vty, struct route_map *map) /* Exit Policy */ vty_out (vty, " Action:%s", VTY_NEWLINE); - if (index->exitpolicy == RMAP_GOTO) - vty_out (vty, " Goto %d%s", index->nextpref, VTY_NEWLINE); - else if (index->exitpolicy == RMAP_NEXT) - vty_out (vty, " Continue to next entry%s", VTY_NEWLINE); - else if (index->exitpolicy == RMAP_EXIT) - vty_out (vty, " Exit routemap%s", VTY_NEWLINE); + switch (index->exitpolicy) + { + case RMAP_GOTO: + vty_out (vty, " Goto %lu%s", (unsigned long)index->goto_seq, + VTY_NEWLINE); + confirm(sizeof(index->goto_seq) <= sizeof(unsigned long)) ; + break ; + + case RMAP_NEXT: + vty_out (vty, " Continue to next entry%s", VTY_NEWLINE); + break ; + + case RMAP_EXIT: + vty_out (vty, " Exit routemap%s", VTY_NEWLINE); + break ; + + default: + zabort("invalid route-map 'exitpolicy'") ; + } ; } } @@ -329,13 +343,12 @@ route_map_index_delete (struct route_map_index *index, int notify) /* Lookup index from route map. */ static struct route_map_index * route_map_index_lookup (struct route_map *map, enum route_map_type type, - int pref) + route_map_seq_t seq) { struct route_map_index *index; for (index = map->head; index; index = index->next) - if ((index->type == type || type == RMAP_ANY) - && index->pref == pref) + if ((index->type == type || type == RMAP_ANY) && index->seq == seq) return index; return NULL; } @@ -343,20 +356,20 @@ route_map_index_lookup (struct route_map *map, enum route_map_type type, /* Add new index to route map. */ static struct route_map_index * route_map_index_add (struct route_map *map, enum route_map_type type, - int pref) + route_map_seq_t seq) { struct route_map_index *index; struct route_map_index *point; - /* Allocate new route map inex. */ + /* Allocate new route map index. */ index = route_map_index_new (); - index->map = map; + index->map = map; index->type = type; - index->pref = pref; + index->seq = seq; - /* Compare preference. */ + /* Compare sequence number */ for (point = map->head; point; point = point->next) - if (point->pref >= pref) + if (point->seq >= seq) break; if (map->head == NULL) @@ -395,11 +408,11 @@ route_map_index_add (struct route_map *map, enum route_map_type type, /* Get route map index. */ static struct route_map_index * route_map_index_get (struct route_map *map, enum route_map_type type, - int pref) + route_map_seq_t seq) { struct route_map_index *index; - index = route_map_index_lookup (map, RMAP_ANY, pref); + index = route_map_index_lookup (map, RMAP_ANY, seq); if (index && index->type != type) { /* Delete index from route map. */ @@ -407,7 +420,7 @@ route_map_index_get (struct route_map *map, enum route_map_type type, index = NULL; } if (index == NULL) - index = route_map_index_add (map, type, pref); + index = route_map_index_add (map, type, seq); return index; } @@ -713,7 +726,7 @@ route_map_delete_set (struct route_map_index *index, const char *set_name, -If Call statement is present jump to the specified route-map, if it denies the route we finish. -If NEXT is specified, goto NEXT statement - -If GOTO is specified, goto the first clause where pref > nextpref + -If GOTO is specified, goto the first clause where seq > goto_seq -If nothing is specified, do as Cisco and finish deny) -Route is denied by route-map. @@ -838,9 +851,9 @@ route_map_apply (struct route_map *map, struct prefix *prefix, { /* Find the next clause to jump to */ struct route_map_index *next = index->next; - int nextpref = index->nextpref; + route_map_seq_t goto_seq = index->goto_seq; - while (next && next->pref < nextpref) + while (next && next->seq < goto_seq) { index = next; next = next->next; @@ -902,7 +915,7 @@ route_map_finish (void) /* VTY related functions. */ DEFUN (route_map, route_map_cmd, - "route-map WORD (deny|permit) <1-65535>", + "route-map WORD (deny|permit) <1-4294967295>", "Create route-map or enter route-map command mode\n" "Route map tag\n" "Route map denies set operations\n" @@ -910,7 +923,7 @@ DEFUN (route_map, "Sequence to insert to/delete from existing route-map entry\n") { int permit; - unsigned long pref; + unsigned long seq; struct route_map *map; struct route_map_index *index; char *endptr = NULL; @@ -926,23 +939,24 @@ DEFUN (route_map, return CMD_WARNING; } - /* Preference check. */ - pref = strtoul (argv[2], &endptr, 10); - if (pref == ULONG_MAX || *endptr != '\0') + /* Sequence number check. */ + seq = strtoul (argv[2], &endptr, 10); + confirm(sizeof(route_map_seq_t) <= sizeof(unsigned long)) ; + if (seq == 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) + if (seq == 0 || seq > 4294967295) { - vty_out (vty, "the fourth field must be <1-65535>%s", VTY_NEWLINE); + vty_out (vty, "the fourth field must be <1-4294967295>%s", VTY_NEWLINE); return CMD_WARNING; } /* Get route map. */ map = route_map_get (argv[0]); - index = route_map_index_get (map, permit, pref); + index = route_map_index_get (map, permit, seq); vty->index = index; vty_set_node(vty, RMAP_NODE) ; @@ -973,7 +987,7 @@ DEFUN (no_route_map_all, DEFUN (no_route_map, no_route_map_cmd, - "no route-map WORD (deny|permit) <1-65535>", + "no route-map WORD (deny|permit) <1-4294967295>", NO_STR "Create route-map or enter route-map command mode\n" "Route map tag\n" @@ -982,7 +996,7 @@ DEFUN (no_route_map, "Sequence to insert to/delete from existing route-map entry\n") { int permit; - unsigned long pref; + unsigned long seq; struct route_map *map; struct route_map_index *index; char *endptr = NULL; @@ -998,17 +1012,18 @@ DEFUN (no_route_map, return CMD_WARNING; } - /* Preference. */ - pref = strtoul (argv[2], &endptr, 10); - if (pref == ULONG_MAX || *endptr != '\0') + /* Sequence number */ + seq = strtoul (argv[2], &endptr, 10); + confirm(sizeof(route_map_seq_t) <= sizeof(unsigned long)) ; + if (seq == 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) + if (seq == 0 || seq > 4294967295) { - vty_out (vty, "the fourth field must be <1-65535>%s", VTY_NEWLINE); + vty_out (vty, "the fourth field must be <1-4294967295>%s", VTY_NEWLINE); return CMD_WARNING; } @@ -1022,7 +1037,7 @@ DEFUN (no_route_map, } /* Lookup route map index. */ - index = route_map_index_lookup (map, permit, pref); + index = route_map_index_lookup (map, permit, seq); if (index == NULL) { vty_out (vty, "%% Could not find route-map entry %s %s%s", @@ -1075,22 +1090,23 @@ DEFUN (no_rmap_onmatch_next, DEFUN (rmap_onmatch_goto, rmap_onmatch_goto_cmd, - "on-match goto <1-65535>", + "on-match goto <1-4294967295>", "Exit policy on matches\n" "Goto Clause number\n" "Number\n") { struct route_map_index *index = vty->index; - int d = 0; + route_map_seq_t d = 0; if (index) { if (argc == 1 && argv[0]) - VTY_GET_INTEGER_RANGE("route-map index", d, argv[0], 1, 65536); + /* TODO: why did the on-match goto range include 65536 ? */ + VTY_GET_INTEGER_RANGE("route-map index", d, argv[0], 1, 4294967295); else - d = index->pref + 1; + d = index->seq + 1; - if (d <= index->pref) + if (d <= index->seq) { /* Can't allow you to do that, Dave */ vty_out (vty, "can't jump backwards in route-maps%s", @@ -1100,7 +1116,7 @@ DEFUN (rmap_onmatch_goto, else { index->exitpolicy = RMAP_GOTO; - index->nextpref = d; + index->goto_seq = d; } } return CMD_SUCCESS; @@ -1138,13 +1154,13 @@ ALIAS (no_rmap_onmatch_goto, /* GNU Zebra compatible */ ALIAS (rmap_onmatch_goto, rmap_continue_seq_cmd, - "continue <1-65535>", + "continue <1-4294967295>", "Continue on a different entry within the route-map\n" "Route-map entry sequence number\n") ALIAS (no_rmap_onmatch_goto, no_rmap_continue_seq, - "no continue <1-65535>", + "no continue <1-4294967295>", NO_STR "Continue on a different entry within the route-map\n" "Route-map entry sequence number\n") @@ -1164,7 +1180,7 @@ DEFUN (rmap_show_name, ALIAS (rmap_onmatch_goto, rmap_continue_index_cmd, - "continue <1-65536>", + "continue <1-4294967295>", "Exit policy on matches\n" "Goto Clause number\n") @@ -1259,10 +1275,11 @@ route_map_config_write (struct vty *vty) else first = 0; - vty_out (vty, "route-map %s %s %d%s", + vty_out (vty, "route-map %s %s %lu%s", map->name, route_map_type_str (index->type), - index->pref, VTY_NEWLINE); + (unsigned long)index->seq, VTY_NEWLINE); + confirm(sizeof(index->seq) <= sizeof(unsigned long)) ; if (index->description) vty_out (vty, " description %s%s", index->description, VTY_NEWLINE); @@ -1276,12 +1293,15 @@ route_map_config_write (struct vty *vty) vty_out (vty, " set %s %s%s", rule->cmd->str, rule->rule_str ? rule->rule_str : "", VTY_NEWLINE); - if (index->nextrm) - vty_out (vty, " call %s%s", index->nextrm, 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); + + if (index->nextrm) + vty_out (vty, " call %s%s", index->nextrm, VTY_NEWLINE); + if (index->exitpolicy == RMAP_GOTO) + vty_out (vty, " on-match goto %lu%s", (unsigned long)index->goto_seq, + VTY_NEWLINE); + confirm(sizeof(index->goto_seq) <= sizeof(unsigned long)) ; + if (index->exitpolicy == RMAP_NEXT) + vty_out (vty," on-match next%s", VTY_NEWLINE); write++; } diff --git a/lib/routemap.h b/lib/routemap.h index 5ff8e334..ac6cb999 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -22,6 +22,8 @@ #ifndef _ZEBRA_ROUTEMAP_H #define _ZEBRA_ROUTEMAP_H +#include <stdint.h> + /* Route map's type. */ enum route_map_type { @@ -107,25 +109,28 @@ struct route_map_rule_list struct route_map_rule *tail; }; -/* Route map index structure. */ +/* Route map sequence number */ +typedef uint32_t route_map_seq_t ; + +/* Route map index structure. */ struct route_map_index { struct route_map *map; char *description; /* Preference of this route map rule. */ - int pref; + route_map_seq_t seq; /* Route map type permit or deny. */ - enum route_map_type type; + enum route_map_type type; /* Do we follow old rules, or hop forward? */ - route_map_end_t exitpolicy; + route_map_end_t exitpolicy; /* If we're using "GOTO", to where do we go? */ - int nextpref; + route_map_seq_t goto_seq; - /* If we're using "CALL", to which route-map do ew go? */ + /* If we're using "CALL", to which route-map do we go? */ char *nextrm; /* Matching rule list. */ |