route_match_ip_next_hop_type_free
};
+/* `match source-protocol` */
+static enum route_map_cmd_result_t
+route_match_source_protocol(void *rule, const struct prefix *prefix,
+ void *object)
+{
+ struct bgp_path_info *path = object;
+ int *protocol = rule;
+
+ if (!path)
+ return RMAP_NOMATCH;
+
+ if (path->type == *protocol)
+ return RMAP_MATCH;
+
+ return RMAP_NOMATCH;
+}
+
+static void *route_match_source_protocol_compile(const char *arg)
+{
+ int *protocol;
+
+ protocol = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*protocol));
+ *protocol = proto_name2num(arg);
+
+ return protocol;
+}
+
+static void route_match_source_protocol_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static const struct route_map_rule_cmd route_match_source_protocol_cmd = {
+ "source-protocol",
+ route_match_source_protocol,
+ route_match_source_protocol_compile,
+ route_match_source_protocol_free
+};
+
+
/* `match ip route-source prefix-list PREFIX_LIST' */
static enum route_map_cmd_result_t
return nb_cli_apply_changes(vty, NULL);
}
+DEFPY_YANG (match_source_protocol,
+ match_source_protocol_cmd,
+ "match source-protocol " FRR_REDIST_STR_ZEBRA "$proto",
+ MATCH_STR
+ "Match protocol via which the route was learnt\n"
+ FRR_REDIST_HELP_STR_ZEBRA)
+{
+ const char *xpath =
+ "./match-condition[condition='frr-bgp-route-map:source-protocol']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/frr-bgp-route-map:source-protocol",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, proto);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG (no_match_source_protocol,
+ no_match_source_protocol_cmd,
+ "no match source-protocol [" FRR_REDIST_STR_ZEBRA "]",
+ NO_STR
+ MATCH_STR
+ "Match protocol via which the route was learnt\n"
+ FRR_REDIST_HELP_STR_ZEBRA)
+{
+ const char *xpath =
+ "./match-condition[condition='frr-bgp-route-map:source-protocol']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
/* Initialization of route map. */
void bgp_route_map_init(void)
{
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
route_map_install_match(&route_match_ip_next_hop_type_cmd);
+ route_map_install_match(&route_match_source_protocol_cmd);
route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
route_map_install_match(&route_match_aspath_cmd);
route_map_install_match(&route_match_community_cmd);
install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
install_element(RMAP_NODE, &match_rpki_extcommunity_cmd);
+ install_element(RMAP_NODE, &match_source_protocol_cmd);
+ install_element(RMAP_NODE, &no_match_source_protocol_cmd);
#ifdef HAVE_SCRIPTING
install_element(RMAP_NODE, &match_script_cmd);
#endif
.destroy = lib_route_map_entry_match_condition_rmap_match_condition_source_vrf_destroy,
}
},
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:source-protocol",
+ .cbs = {
+ .modify = lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_modify,
+ .destroy = lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_destroy,
+ }
+ },
{
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address",
.cbs = {
struct nb_cb_modify_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_destroy(
struct nb_cb_destroy_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_modify(
+ struct nb_cb_modify_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_destroy(
+ struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_probability_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_probability_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_source_vrf_modify(struct nb_cb_modify_args *args);
return NB_OK;
}
+/*
+ * XPath:
+ * /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:source-protocol
+ */
+int lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct routemap_hook_context *rhc;
+ enum rmap_compile_rets ret;
+ const char *proto;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ /* Add configuration. */
+ rhc = nb_running_get_entry(args->dnode, NULL, true);
+ proto = yang_dnode_get_string(args->dnode, NULL);
+
+ /* Set destroy information. */
+ rhc->rhc_mhook = bgp_route_match_delete;
+ rhc->rhc_rule = "source-protocol";
+ rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
+
+ ret = bgp_route_match_add(rhc->rhc_rmi, "source-protocol",
+ proto, RMAP_EVENT_MATCH_ADDED,
+ args->errmsg, args->errmsg_len);
+
+ if (ret != RMAP_COMPILE_SUCCESS) {
+ rhc->rhc_mhook = NULL;
+ return NB_ERR_INCONSISTENCY;
+ }
+ }
+
+ return NB_OK;
+}
+
+int lib_route_map_entry_match_condition_rmap_match_condition_source_protocol_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_match_destroy(args);
+ }
+
+ return NB_OK;
+}
+
/*
* XPath:
* /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity
(strmatch(C, "frr-zebra-route-map:ipv4-next-hop-prefix-length"))
#define IS_MATCH_SRC_PROTO(C) \
(strmatch(C, "frr-zebra-route-map:source-protocol"))
+#define IS_MATCH_BGP_SRC_PROTO(C) \
+ (strmatch(C, "frr-bgp-route-map:source-protocol"))
#define IS_MATCH_SRC_INSTANCE(C) \
(strmatch(C, "frr-zebra-route-map:source-instance"))
/* BGP route-map match conditions */
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length"));
- } else if (IS_MATCH_SRC_PROTO(condition)) {
+ } else if (IS_MATCH_SRC_PROTO(condition) ||
+ IS_MATCH_BGP_SRC_PROTO(condition)) {
vty_out(vty, " match source-protocol %s\n",
yang_dnode_get_string(
dnode,
- "./rmap-match-condition/frr-zebra-route-map:source-protocol"));
+ IS_MATCH_SRC_PROTO(condition)
+ ? "./rmap-match-condition/frr-zebra-route-map:source-protocol"
+ : "./rmap-match-condition/frr-bgp-route-map:source-protocol"));
} else if (IS_MATCH_SRC_INSTANCE(condition)) {
vty_out(vty, " match source-instance %s\n",
yang_dnode_get_string(
prefix rt-types;
}
+ import frr-route-types {
+ prefix frr-route-types;
+ }
+
organization
"Free Range Routing";
contact
"Match IPv6 next hop address";
}
+ identity source-protocol {
+ base frr-route-map:rmap-match-type;
+ description
+ "Match protocol via which the route was learnt";
+ }
+
identity distance {
base frr-route-map:rmap-set-type;
description
"IPv6 address";
}
}
+
+ case source-protocol {
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:source-protocol')";
+ leaf source-protocol {
+ type frr-route-types:frr-route-types;
+ }
+ }
}
augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:rmap-set-action/frr-route-map:set-action" {