2003-10-29 Paul Jakma <paul@dishone.st>
* lib/routemap.c: (route_map_apply_index) renamed to
route_map_apply_match.
(route_map_apply_match) Take rule list as argument rather than
index. concentrate solely on match logic.
(route_map_apply) Properly implement the route map statement
logic, according to the table, especially the on-match exit
policy.
diff --git a/lib/routemap.c b/lib/routemap.c
index b000f2f..68ac23d 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -634,122 +634,137 @@
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) Finish route-map processing, and deny route
-** 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_t
-route_map_apply_index (struct route_map_index *index, struct prefix *prefix,
- route_map_object_t type, void *object)
-{
- int ret;
- struct route_map_rule *match;
- struct route_map_rule *set;
+/* 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
- /* Check all match rule and if there is no match rule return 0. */
- for (match = index->match_list.head; match; match = match->next)
- {
- /* Try each match statement in turn. If any return something
- other than RM_MATCH then we don't need to check anymore and can
- return */
- ret = (*match->cmd->func_apply)(match->value, prefix, type, object);
- if (ret != RMAP_MATCH)
- return ret;
- }
+ Match | No Match
+ |
+ permit action | cont
+ |
+ ------------------+---------------
+ |
+ deny deny | cont
+ |
+
+ action) 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
+ deny) If NEXT is specified, goto NEXT statement
+ If nothing is specified, finally will be denied by route-map.
+ cont) 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
+*/
- /* 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 */
+route_map_result_t
+route_map_apply_match (struct route_map_rule_list *match_list,
+ struct prefix *prefix, route_map_object_t type,
+ void *object)
+{
+ route_map_result_t ret = RMAP_NOMATCH;
+ struct route_map_rule *match;
- /* Apply set statement to the object. */
- if (index->type == RMAP_PERMIT)
+
+ /* Check all match rule and if there is no match rule, go to the
+ set statement. */
+ if (!match_list->head)
+ ret = RMAP_MATCH;
+ else
{
- for (set = index->set_list.head; set; set = set->next)
- {
- ret = (*set->cmd->func_apply)(set->value, prefix, type, object);
- }
- return RMAP_MATCH;
+ for (match = match_list->head; match; match = match->next)
+ {
+ /* Try each match statement in turn, If any do not return
+ RMAP_MATCH, return, otherwise continue on to next match
+ statement. All match statements must match for end-result
+ to be a match. */
+ ret = (*match->cmd->func_apply) (match->value, prefix,
+ type, object);
+ if (ret != RMAP_MATCH)
+ return ret;
+ }
}
- else
- {
- return RMAP_DENYMATCH;
- }
- /* Should not get here! */
- return RMAP_MATCH;
+ return ret;
}
/* Apply route map to the object. */
route_map_result_t
-route_map_apply (struct route_map *map, struct prefix *prefix,
- route_map_object_t type, void *object)
+route_map_apply (struct route_map *map, struct prefix *prefix,
+ route_map_object_t type, void *object)
{
int ret = 0;
struct route_map_index *index;
+ struct route_map_rule *set;
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);
+ /* Apply this index. */
+ ret = route_map_apply_match (&index->match_list, prefix, type, object);
- 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;
+ /* Now we apply the matrix from above */
+ if (ret == RMAP_NOMATCH)
+ /* 'cont' from matrix - continue to next route-map sequence */
+ continue;
+ else if (ret == RMAP_MATCH)
+ {
+ if (index->type == RMAP_PERMIT)
+ /* 'action' */
+ {
+ /* permit+match must execute sets */
+ for (set = index->set_list.head; set; set = set->next)
+ ret = (*set->cmd->func_apply) (set->value, prefix,
+ type, object);
+ switch (index->exitpolicy)
+ {
+ case RMAP_EXIT:
+ return ret;
+ case RMAP_NEXT:
+ continue;
+ case RMAP_GOTO:
+ {
+ /* Find the next clause to jump to */
+ struct route_map_index *next = 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 */
- }
+ while (next && next->pref < index->nextpref)
+ {
+ index = next;
+ next = next->next;
+ }
+ if (next == NULL)
+ {
+ /* No clauses match! */
+ return ret;
+ }
+ }
+ }
+ }
+ else if (index->type == RMAP_DENY)
+ /* 'deny' */
+ {
+ if (index->exitpolicy == RMAP_NEXT)
+ continue;
+ else
+ return RMAP_DENYMATCH;
+ }
+ }
}
/* Finally route-map does not match at all. */
return RMAP_DENYMATCH;