#include "plist.h"
#include "nexthop.h"
#include "vrf.h"
+#include "frrstr.h"
#include "zebra/zserv.h"
#include "zebra/redistribute.h"
#include "zebra/zebra_rnh.h"
#include "zebra/zebra_routemap.h"
-static u_int32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER;
+static uint32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER;
static struct thread *zebra_t_rmap_update = NULL;
char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */
/* NH Tracking route map */
struct nh_rmap_obj {
struct nexthop *nexthop;
vrf_id_t vrf_id;
- u_int32_t source_protocol;
+ uint32_t source_protocol;
+ uint8_t instance;
int metric;
route_tag_t tag;
};
-static void zebra_route_map_set_delay_timer(u_int32_t value);
+static void zebra_route_map_set_delay_timer(uint32_t value);
/* Add zebra route map rule */
/* 'match tag TAG'
* Match function return 1 if match is success else return 0
*/
-static route_map_result_t route_match_tag(void *rule, struct prefix *prefix,
+static route_map_result_t route_match_tag(void *rule,
+ const struct prefix *prefix,
route_map_object_t type, void *object)
{
route_tag_t *tag;
/* `match interface IFNAME' */
/* Match function return 1 if match is success else return zero. */
static route_map_result_t route_match_interface(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
"Match prefix length of ipv6 address\n"
"Prefix length\n")
{
- return zebra_route_match_add(vty, "ipv6 address prefix-len", argv[4]->arg,
- RMAP_EVENT_MATCH_ADDED);
+ return zebra_route_match_add(vty, "ipv6 address prefix-len",
+ argv[4]->arg, RMAP_EVENT_MATCH_ADDED);
}
DEFUN (no_match_ipv6_address_prefix_len,
DEFUN (match_source_protocol,
match_source_protocol_cmd,
- "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>",
+ "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>",
MATCH_STR
"Match protocol via which the route was learnt\n"
"BGP protocol\n"
"Routes from directly connected peer\n"
"Routes from system configuration\n"
"Routes from kernel\n"
- "Statically configured routes\n")
+ "Statically configured routes\n"
+ "SHARP process\n")
{
char *proto = argv[2]->text;
int i;
DEFUN (no_match_source_protocol,
no_match_source_protocol_cmd,
- "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>]",
+ "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>]",
NO_STR
MATCH_STR
"No match protocol via which the route was learnt\n"
"Routes from directly connected peer\n"
"Routes from system configuration\n"
"Routes from kernel\n"
- "Statically configured routes\n")
+ "Statically configured routes\n"
+ "SHARP process\n")
{
char *proto = (argc == 4) ? argv[3]->text : NULL;
return zebra_route_match_delete(vty, "source-protocol", proto,
RMAP_EVENT_MATCH_DELETED);
}
+DEFUN (match_source_instance,
+ match_source_instance_cmd,
+ "match source-instance (0-255)",
+ MATCH_STR
+ "Match the protocol's instance number\n"
+ "The instance number\n")
+{
+ char *instance = argv[2]->arg;
+
+ return zebra_route_match_add(vty, "source-instance", instance,
+ RMAP_EVENT_MATCH_ADDED);
+}
+
+DEFUN (no_match_source_instance,
+ no_match_source_instance_cmd,
+ "no match source-instance [(0-255)]",
+ NO_STR MATCH_STR
+ "Match the protocol's instance number\n"
+ "The instance number\n")
+{
+ char *instance = (argc == 4) ? argv[3]->arg : NULL;
+
+ return zebra_route_match_delete(vty, "source-instance", instance,
+ RMAP_EVENT_MATCH_ADDED);
+}
+
/* set functions */
DEFUN (set_src,
"0 means event-driven updates are disabled\n")
{
int idx_number = 3;
- u_int32_t rmap_delay_timer;
+ uint32_t rmap_delay_timer;
rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10);
zebra_route_map_set_delay_timer(rmap_delay_timer);
/* Match function return 1 if match is success else return zero. */
static route_map_result_t route_match_ip_next_hop(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
/* `match ip next-hop prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
/* Match function should return 1 if match is success else return
zero. */
static route_map_result_t route_match_ip_address(void *rule,
- struct prefix *prefix,
+ const struct prefix *prefix,
route_map_object_t type,
void *object)
{
/* `match ip address prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_address_prefix_list(void *rule, struct prefix *prefix,
+route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct prefix_list *plist;
/* `match ip address prefix-len PREFIXLEN' */
static route_map_result_t
-route_match_address_prefix_len(void *rule, struct prefix *prefix,
+route_match_address_prefix_len(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
- u_int32_t *prefixlen = (u_int32_t *)rule;
+ uint32_t *prefixlen = (uint32_t *)rule;
if (type == RMAP_ZEBRA) {
return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH
static void *route_match_address_prefix_len_compile(const char *arg)
{
- u_int32_t *prefix_len;
+ uint32_t *prefix_len;
char *endptr = NULL;
unsigned long tmpval;
if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
return NULL;
- prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t));
+ prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
if (!prefix_len)
return prefix_len;
/* `match ip nexthop prefix-len PREFIXLEN' */
static route_map_result_t
-route_match_ip_nexthop_prefix_len(void *rule, struct prefix *prefix,
+route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
- u_int32_t *prefixlen = (u_int32_t *)rule;
+ uint32_t *prefixlen = (uint32_t *)rule;
struct nh_rmap_obj *nh_data;
struct prefix_ipv4 p;
/* `match source-protocol PROTOCOL' */
static route_map_result_t route_match_source_protocol(void *rule,
- struct prefix *prefix,
+ const struct prefix *p,
route_map_object_t type,
void *object)
{
- u_int32_t *rib_type = (u_int32_t *)rule;
+ uint32_t *rib_type = (uint32_t *)rule;
struct nh_rmap_obj *nh_data;
if (type == RMAP_ZEBRA) {
static void *route_match_source_protocol_compile(const char *arg)
{
- u_int32_t *rib_type;
+ uint32_t *rib_type;
int i;
i = proto_name2num(arg);
- rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t));
+ rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
*rib_type = i;
"source-protocol", route_match_source_protocol,
route_match_source_protocol_compile, route_match_source_protocol_free};
+/* `source-instance` */
+static route_map_result_t route_match_source_instance(void *rule,
+ const struct prefix *p,
+ route_map_object_t type,
+ void *object)
+{
+ uint8_t *instance = (uint8_t *)rule;
+ struct nh_rmap_obj *nh_data;
+
+ if (type != RMAP_ZEBRA)
+ return RMAP_NOMATCH;
+
+ nh_data = (struct nh_rmap_obj *)object;
+ if (!nh_data)
+ return RMAP_DENYMATCH;
+
+ return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
+}
+
+static void *route_match_source_instance_compile(const char *arg)
+{
+ uint8_t *instance;
+ int i;
+
+ i = atoi(arg);
+ instance = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
+
+ *instance = i;
+
+ return instance;
+}
+
+static void route_match_source_instance_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static struct route_map_rule_cmd route_match_source_instance_cmd = {
+ "source-instance", route_match_source_instance,
+ route_match_source_instance_compile, route_match_source_instance_free};
+
/* `set src A.B.C.D' */
/* Set src. */
-static route_map_result_t route_set_src(void *rule, struct prefix *prefix,
+static route_map_result_t route_set_src(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
struct nh_rmap_obj *nh_data;
"src", route_set_src, route_set_src_compile, route_set_src_free,
};
+static void zebra_route_map_process_update_cb(char *rmap_name)
+{
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("Event handler for route-map: %s",
+ rmap_name);
+}
+
static int zebra_route_map_update_timer(struct thread *thread)
{
zebra_t_rmap_update = NULL;
"%u: Routemap update-timer fired, scheduling RIB processing",
VRF_DEFAULT);
+ route_map_walk_update_list(zebra_route_map_process_update_cb);
+
+ /*
+ * This code needs to be updated to be:
+ * 1) VRF Aware <sigh>
+ * 2) Route-map aware
+ */
zebra_import_table_rm_update();
rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
return (0);
}
-static void zebra_route_map_set_delay_timer(u_int32_t value)
+static void zebra_route_map_set_delay_timer(uint32_t value)
{
zebra_rmap_update_timer = value;
if (!value && zebra_t_rmap_update) {
}
route_map_result_t zebra_route_map_check(int family, int rib_type,
- struct prefix *p,
+ uint8_t instance,
+ const struct prefix *p,
struct nexthop *nexthop,
vrf_id_t vrf_id, route_tag_t tag)
{
nh_obj.nexthop = nexthop;
nh_obj.vrf_id = vrf_id;
nh_obj.source_protocol = rib_type;
+ nh_obj.instance = instance;
nh_obj.metric = 0;
nh_obj.tag = tag;
}
route_map_result_t
-zebra_import_table_route_map_check(int family, int re_type, struct prefix *p,
- struct nexthop *nexthop, vrf_id_t vrf_id,
- route_tag_t tag, const char *rmap_name)
+zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
+ const struct prefix *p,
+ struct nexthop *nexthop,
+ vrf_id_t vrf_id, route_tag_t tag,
+ const char *rmap_name)
{
struct route_map *rmap = NULL;
route_map_result_t ret = RMAP_DENYMATCH;
nh_obj.nexthop = nexthop;
nh_obj.vrf_id = vrf_id;
nh_obj.source_protocol = re_type;
+ nh_obj.instance = instance;
nh_obj.metric = 0;
nh_obj.tag = tag;
}
route_map_result_t zebra_nht_route_map_check(int family, int client_proto,
- struct prefix *p,
+ const struct prefix *p,
struct route_entry *re,
struct nexthop *nexthop)
{
struct nh_rmap_obj nh_obj;
nh_obj.nexthop = nexthop;
- nh_obj.vrf_id = re->nh_vrf_id;
+ nh_obj.vrf_id = nexthop->vrf_id;
nh_obj.source_protocol = re->type;
+ nh_obj.instance = re->instance;
nh_obj.metric = re->metric;
nh_obj.tag = re->tag;
if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX])
rmap = route_map_lookup_by_name(
nht_rm[family][ZEBRA_ROUTE_MAX]);
- if (rmap) {
+ if (rmap)
ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
- }
- return (ret);
+ return ret;
}
static void zebra_route_map_mark_update(const char *rmap_name)
static void zebra_route_map_add(const char *rmap_name)
{
- zebra_route_map_mark_update(rmap_name);
+ if (route_map_mark_updated(rmap_name) == 0)
+ zebra_route_map_mark_update(rmap_name);
+
route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
}
static void zebra_route_map_delete(const char *rmap_name)
{
- zebra_route_map_mark_update(rmap_name);
+ if (route_map_mark_updated(rmap_name) == 0)
+ zebra_route_map_mark_update(rmap_name);
+
route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
}
static void zebra_route_map_event(route_map_event_t event,
const char *rmap_name)
{
- zebra_route_map_mark_update(rmap_name);
+ if (route_map_mark_updated(rmap_name) == 0)
+ zebra_route_map_mark_update(rmap_name);
+
route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
}
route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
route_map_install_match(&route_match_source_protocol_cmd);
+ route_map_install_match(&route_match_source_instance_cmd);
+
/* */
route_map_install_set(&route_set_src_cmd);
/* */
install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
install_element(RMAP_NODE, &match_source_protocol_cmd);
install_element(RMAP_NODE, &no_match_source_protocol_cmd);
+ install_element(RMAP_NODE, &match_source_instance_cmd);
+ install_element(RMAP_NODE, &no_match_source_instance_cmd);
+
/* */
install_element(RMAP_NODE, &set_src_cmd);
install_element(RMAP_NODE, &no_set_src_cmd);