From: Quentin Young Date: Thu, 20 Oct 2016 16:31:49 +0000 (+0000) Subject: Merge branch 'cmaster-next' into vtysh-grammar X-Git-Tag: frr-3.0-branchpoint~129^2~75 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=0a538fc98fb662b4cf2d927ac29fd9af4a4fab03;p=mirror%2Ffrr.git Merge branch 'cmaster-next' into vtysh-grammar Signed-off-by: Quentin Young Conflicts: isisd/isis_routemap.c zebra/rt_netlink.c --- 0a538fc98fb662b4cf2d927ac29fd9af4a4fab03 diff --cc isisd/isis_routemap.c index 93267afe92,1f947fb047..1d734fbc2f --- a/isisd/isis_routemap.c +++ b/isisd/isis_routemap.c @@@ -250,30 -250,314 +250,29 @@@ static struct route_map_rule_cmd route_ route_set_metric_free }; -/* ------------------------------------------------------------*/ - -static int -isis_route_match_add(struct vty *vty, - const char *command, const char *arg) -{ - VTY_DECLVAR_CONTEXT (route_map_index, index); - int ret; - - ret = route_map_add_match (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); - return CMD_WARNING; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); - return CMD_WARNING; - } - } - return CMD_SUCCESS; -} - -static int -isis_route_match_delete(struct vty *vty, - const char *command, const char *arg) -{ - VTY_DECLVAR_CONTEXT (route_map_index, index); - int ret; - - ret = route_map_delete_match (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); - return CMD_WARNING; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); - return CMD_WARNING; - } - } - return CMD_SUCCESS; -} - -static int -isis_route_set_add(struct vty *vty, - const char *command, const char *arg) -{ - VTY_DECLVAR_CONTEXT (route_map_index, index); - int ret; - - ret = route_map_add_set(index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); - return CMD_WARNING; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); - return CMD_WARNING; - } - } - - return CMD_SUCCESS; -} - -static int -isis_route_set_delete (struct vty *vty, - const char *command, const char *arg) -{ - VTY_DECLVAR_CONTEXT (route_map_index, index); - int ret; - - ret = route_map_delete_set (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); - return CMD_WARNING; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); - return CMD_WARNING; - } - } - - return CMD_SUCCESS; -} - -/* ------------------------------------------------------------*/ - -DEFUN (match_ip_address, - match_ip_address_cmd, - "match ip address (<1-199>|<1300-2699>|WORD)", - MATCH_STR - IP_STR - "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP Access-list name\n") -{ - return isis_route_match_add(vty, "ip address", argv[0]); -} - -DEFUN (no_match_ip_address, - no_match_ip_address_val_cmd, - "no match ip address (<1-199>|<1300-2699>|WORD)", - NO_STR - MATCH_STR - IP_STR - "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP Access-list name\n") -{ - if (argc == 0) - return isis_route_match_delete(vty, "ip address", NULL); - return isis_route_match_delete(vty, "ip address", argv[0]); -} - -ALIAS (no_match_ip_address, - no_match_ip_address_cmd, - "no match ip address", - NO_STR - MATCH_STR - IP_STR - "Match address of route\n") - -/* ------------------------------------------------------------*/ - -DEFUN (match_ip_address_prefix_list, - match_ip_address_prefix_list_cmd, - "match ip address prefix-list WORD", - MATCH_STR - IP_STR - "Match address of route\n" - "Match entries of prefix-lists\n" - "IP prefix-list name\n") -{ - return isis_route_match_add(vty, "ip address prefix-list", argv[0]); -} - -DEFUN (no_match_ip_address_prefix_list, - no_match_ip_address_prefix_list_cmd, - "no match ip address prefix-list", - NO_STR - MATCH_STR - IP_STR - "Match address of route\n" - "Match entries of prefix-lists\n") -{ - if (argc == 0) - return isis_route_match_delete (vty, "ip address prefix-list", NULL); - return isis_route_match_delete (vty, "ip address prefix-list", argv[0]); -} - -ALIAS (no_match_ip_address_prefix_list, - no_match_ip_address_prefix_list_val_cmd, - "no match ip address prefix-list WORD", - NO_STR - MATCH_STR - IP_STR - "Match address of route\n" - "Match entries of prefix-lists\n" - "IP prefix-list name\n") - -/* ------------------------------------------------------------*/ - -DEFUN (match_ipv6_address, - match_ipv6_address_cmd, - "match ipv6 address WORD", - MATCH_STR - IPV6_STR - "Match IPv6 address of route\n" - "IPv6 access-list name\n") -{ - return isis_route_match_add(vty, "ipv6 address", argv[0]); -} - -DEFUN (no_match_ipv6_address, - no_match_ipv6_address_val_cmd, - "no match ipv6 address WORD", - NO_STR - MATCH_STR - IPV6_STR - "Match IPv6 address of route\n" - "IPv6 access-list name\n") -{ - if (argc == 0) - return isis_route_match_delete(vty, "ipv6 address", NULL); - return isis_route_match_delete(vty, "ipv6 address", argv[0]); -} - -ALIAS (no_match_ipv6_address, - no_match_ipv6_address_cmd, - "no match ipv6 address", - NO_STR - MATCH_STR - IPV6_STR - "Match IPv6 address of route\n") - -/* ------------------------------------------------------------*/ - -DEFUN (match_ipv6_address_prefix_list, - match_ipv6_address_prefix_list_cmd, - "match ipv6 address prefix-list WORD", - MATCH_STR - IPV6_STR - "Match address of route\n" - "Match entries of prefix-lists\n" - "IP prefix-list name\n") -{ - return isis_route_match_add(vty, "ipv6 address prefix-list", argv[0]); -} - -DEFUN (no_match_ipv6_address_prefix_list, - no_match_ipv6_address_prefix_list_cmd, - "no match ipv6 address prefix-list", - NO_STR - MATCH_STR - IPV6_STR - "Match address of route\n" - "Match entries of prefix-lists\n") +void +isis_route_map_init(void) { - if (argc == 0) - return isis_route_match_delete (vty, "ipv6 address prefix-list", NULL); - return isis_route_match_delete (vty, "ipv6 address prefix-list", argv[0]); -} + route_map_init(); - route_map_init_vty(); -ALIAS (no_match_ipv6_address_prefix_list, - no_match_ipv6_address_prefix_list_val_cmd, - "no match ipv6 address prefix-list WORD", - NO_STR - MATCH_STR - IPV6_STR - "Match address of route\n" - "Match entries of prefix-lists\n" - "IP prefix-list name\n") + route_map_match_ip_address_hook (generic_match_add); + route_map_no_match_ip_address_hook (generic_match_delete); -/* ------------------------------------------------------------*/ + route_map_match_ip_address_prefix_list_hook (generic_match_add); + route_map_no_match_ip_address_prefix_list_hook (generic_match_delete); -/* set metric already exists e.g. in the ospf routemap. vtysh doesn't cope well with different - * commands at the same node, therefore add set metric with the same 32-bit range as ospf and - * verify that the input is a valid isis metric */ -DEFUN (set_metric, - set_metric_cmd, - "set metric <0-4294967295>", - SET_STR - "Metric vale for destination routing protocol\n" - "Metric value\n") -{ - return isis_route_set_add(vty, "metric", argv[0]); -} + route_map_match_ipv6_address_hook (generic_match_add); + route_map_no_match_ipv6_address_hook (generic_match_delete); -DEFUN (no_set_metric, - no_set_metric_val_cmd, - "no set metric <0-4294967295>", - NO_STR - SET_STR - "Metric value for destination routing protocol\n" - "Metric value\n") -{ - if (argc == 0) - return isis_route_set_delete(vty, "metric", NULL); - return isis_route_set_delete(vty, "metric", argv[0]); -} + route_map_match_ipv6_address_prefix_list_hook (generic_match_add); + route_map_no_match_ipv6_address_prefix_list_hook (generic_match_delete); -ALIAS (no_set_metric, - no_set_metric_cmd, - "no set metric", - NO_STR - SET_STR - "Metric vale for destination routing protocol\n"); - -void -isis_route_map_init(void) -{ - route_map_init(); + route_map_set_metric_hook (generic_set_add); + route_map_no_set_metric_hook (generic_set_delete); route_map_install_match(&route_match_ip_address_cmd); - install_element(RMAP_NODE, &match_ip_address_cmd); - install_element(RMAP_NODE, &no_match_ip_address_val_cmd); - install_element(RMAP_NODE, &no_match_ip_address_cmd); - route_map_install_match(&route_match_ip_address_prefix_list_cmd); - install_element(RMAP_NODE, &match_ip_address_prefix_list_cmd); - install_element(RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd); - install_element(RMAP_NODE, &no_match_ip_address_prefix_list_cmd); - route_map_install_match(&route_match_ipv6_address_cmd); - install_element(RMAP_NODE, &match_ipv6_address_cmd); - install_element(RMAP_NODE, &no_match_ipv6_address_val_cmd); - install_element(RMAP_NODE, &no_match_ipv6_address_cmd); - route_map_install_match(&route_match_ipv6_address_prefix_list_cmd); - install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd); - install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_val_cmd); - install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd); - route_map_install_set(&route_set_metric_cmd); - install_element(RMAP_NODE, &set_metric_cmd); - install_element(RMAP_NODE, &no_set_metric_val_cmd); - install_element(RMAP_NODE, &no_set_metric_cmd); } diff --cc lib/Makefile.am index dbf1a82be2,1c0906837a..f0d5bd53db --- a/lib/Makefile.am +++ b/lib/Makefile.am @@@ -20,9 -17,10 +20,10 @@@ libzebra_la_SOURCES = sigevent.c pqueue.c jhash.c workqueue.c nexthop.c json.c \ ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c memory.c memory_vty.c \ imsg-buffer.c imsg.c skiplist.c \ - qobj.c + qobj.c \ + event_counter.c -BUILT_SOURCES = route_types.h gitversion.h +BUILT_SOURCES = route_types.h gitversion.h command_parse.h libzebra_la_DEPENDENCIES = @LIB_REGEX@ diff --cc lib/routemap.h index 86d72ce474,b5cdd27277..b52f7289b0 --- a/lib/routemap.h +++ b/lib/routemap.h @@@ -25,6 -25,6 +25,8 @@@ #include "prefix.h" #include "memory.h" #include "qobj.h" ++#include "vty.h" ++ DECLARE_MTYPE(ROUTE_MAP_NAME) DECLARE_MTYPE(ROUTE_MAP_RULE) DECLARE_MTYPE(ROUTE_MAP_COMPILED) diff --cc ripd/rip_routemap.c index 60ce66265e,8b48adfd55..6fd647596c --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@@ -588,50 -685,394 +588,50 @@@ static struct route_map_rule_cmd route_ #define MATCH_STR "Match values from routing table\n" #define SET_STR "Set values in destination routing protocol\n" -DEFUN (match_metric, - match_metric_cmd, - "match metric <0-4294967295>", - MATCH_STR - "Match metric of route\n" - "Metric value\n") -{ - return rip_route_match_add (vty, vty->index, "metric", argv[0]); -} - -DEFUN (no_match_metric, - no_match_metric_cmd, - "no match metric", - NO_STR - MATCH_STR - "Match metric of route\n") -{ - if (argc == 0) - return rip_route_match_delete (vty, vty->index, "metric", NULL); - - return rip_route_match_delete (vty, vty->index, "metric", argv[0]); -} - -ALIAS (no_match_metric, - no_match_metric_val_cmd, - "no match metric <0-4294967295>", - NO_STR - MATCH_STR - "Match metric of route\n" - "Metric value\n") - -DEFUN (match_interface, - match_interface_cmd, - "match interface WORD", - MATCH_STR - "Match first hop interface of route\n" - "Interface name\n") -{ - return rip_route_match_add (vty, vty->index, "interface", argv[0]); -} - -DEFUN (no_match_interface, - no_match_interface_cmd, - "no match interface", - NO_STR - MATCH_STR - "Match first hop interface of route\n") -{ - if (argc == 0) - return rip_route_match_delete (vty, vty->index, "interface", NULL); - - return rip_route_match_delete (vty, vty->index, "interface", argv[0]); -} - -ALIAS (no_match_interface, - no_match_interface_val_cmd, - "no match interface WORD", - NO_STR - MATCH_STR - "Match first hop interface of route\n" - "Interface name\n") - -DEFUN (match_ip_next_hop, - match_ip_next_hop_cmd, - "match ip next-hop (<1-199>|<1300-2699>|WORD)", - MATCH_STR - IP_STR - "Match next-hop address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP Access-list name\n") -{ - return rip_route_match_add (vty, vty->index, "ip next-hop", argv[0]); -} - -DEFUN (no_match_ip_next_hop, - no_match_ip_next_hop_cmd, - "no match ip next-hop", - NO_STR - MATCH_STR - IP_STR - "Match next-hop address of route\n") -{ - if (argc == 0) - return rip_route_match_delete (vty, vty->index, "ip next-hop", NULL); - - return rip_route_match_delete (vty, vty->index, "ip next-hop", argv[0]); -} - -ALIAS (no_match_ip_next_hop, - no_match_ip_next_hop_val_cmd, - "no match ip next-hop (<1-199>|<1300-2699>|WORD)", - NO_STR - MATCH_STR - IP_STR - "Match next-hop address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP Access-list name\n") - -DEFUN (match_ip_next_hop_prefix_list, - match_ip_next_hop_prefix_list_cmd, - "match ip next-hop prefix-list WORD", - MATCH_STR - IP_STR - "Match next-hop address of route\n" - "Match entries of prefix-lists\n" - "IP prefix-list name\n") -{ - return rip_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]); -} - -DEFUN (no_match_ip_next_hop_prefix_list, - no_match_ip_next_hop_prefix_list_cmd, - "no match ip next-hop prefix-list", - NO_STR - MATCH_STR - IP_STR - "Match next-hop address of route\n" - "Match entries of prefix-lists\n") -{ - if (argc == 0) - return rip_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL); - - return rip_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]); -} - -ALIAS (no_match_ip_next_hop_prefix_list, - no_match_ip_next_hop_prefix_list_val_cmd, - "no match ip next-hop prefix-list WORD", - NO_STR - MATCH_STR - IP_STR - "Match next-hop address of route\n" - "Match entries of prefix-lists\n" - "IP prefix-list name\n") - -DEFUN (match_ip_address, - match_ip_address_cmd, - "match ip address (<1-199>|<1300-2699>|WORD)", - MATCH_STR - IP_STR - "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP Access-list name\n") - -{ - return rip_route_match_add (vty, vty->index, "ip address", argv[0]); -} - -DEFUN (no_match_ip_address, - no_match_ip_address_cmd, - "no match ip address", - NO_STR - MATCH_STR - IP_STR - "Match address of route\n") -{ - if (argc == 0) - return rip_route_match_delete (vty, vty->index, "ip address", NULL); - - return rip_route_match_delete (vty, vty->index, "ip address", argv[0]); -} - -ALIAS (no_match_ip_address, - no_match_ip_address_val_cmd, - "no match ip address (<1-199>|<1300-2699>|WORD)", - NO_STR - MATCH_STR - IP_STR - "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP Access-list name\n") - -DEFUN (match_ip_address_prefix_list, - match_ip_address_prefix_list_cmd, - "match ip address prefix-list WORD", - MATCH_STR - IP_STR - "Match address of route\n" - "Match entries of prefix-lists\n" - "IP prefix-list name\n") -{ - return rip_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]); -} - -DEFUN (no_match_ip_address_prefix_list, - no_match_ip_address_prefix_list_cmd, - "no match ip address prefix-list", - NO_STR - MATCH_STR - IP_STR - "Match address of route\n" - "Match entries of prefix-lists\n") -{ - if (argc == 0) - return rip_route_match_delete (vty, vty->index, "ip address prefix-list", NULL); - - return rip_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]); -} - -ALIAS (no_match_ip_address_prefix_list, - no_match_ip_address_prefix_list_val_cmd, - "no match ip address prefix-list WORD", - NO_STR - MATCH_STR - IP_STR - "Match address of route\n" - "Match entries of prefix-lists\n" - "IP prefix-list name\n") - -DEFUN (match_tag, - match_tag_cmd, - "match tag <1-4294967295>", - MATCH_STR - "Match tag of route\n" - "Metric value\n") -{ - return rip_route_match_add (vty, vty->index, "tag", argv[0]); -} - -DEFUN (no_match_tag, - no_match_tag_cmd, - "no match tag", - NO_STR - MATCH_STR - "Match tag of route\n") -{ - if (argc == 0) - return rip_route_match_delete (vty, vty->index, "tag", NULL); - - return rip_route_match_delete (vty, vty->index, "tag", argv[0]); -} - -ALIAS (no_match_tag, - no_match_tag_val_cmd, - "no match tag <1-4294967295>", - NO_STR - MATCH_STR - "Match tag of route\n" - "Metric value\n") - -/* set functions */ - -DEFUN (set_metric, - set_metric_cmd, - "set metric <0-4294967295>", - SET_STR - "Metric value for destination routing protocol\n" - "Metric value\n") +void +rip_route_map_reset () { - return rip_route_set_add (vty, vty->index, "metric", argv[0]); + ; } -ALIAS (set_metric, - set_metric_addsub_cmd, - "set metric <+/-metric>", - SET_STR - "Metric value for destination routing protocol\n" - "Add or subtract metric\n") - -DEFUN (no_set_metric, - no_set_metric_cmd, - "no set metric", - NO_STR - SET_STR - "Metric value for destination routing protocol\n") +/* Route-map init */ +void +rip_route_map_init () { - if (argc == 0) - return rip_route_set_delete (vty, vty->index, "metric", NULL); + route_map_init (); - route_map_init_vty (); + - return rip_route_set_delete (vty, vty->index, "metric", argv[0]); -} + route_map_add_hook (rip_route_map_update); + route_map_delete_hook (rip_route_map_update); -ALIAS (no_set_metric, - no_set_metric_val_cmd, - "no set metric <0-4294967295>", - NO_STR - SET_STR - "Metric value for destination routing protocol\n" - "Metric value\n") - -ALIAS (no_set_metric, - no_set_metric_addsub_cmd, - "no set metric <+/-metric>", - NO_STR - SET_STR - "Metric value for destination routing protocol\n" - "Add or subtract metric\n") - -DEFUN (set_ip_nexthop, - set_ip_nexthop_cmd, - "set ip next-hop A.B.C.D", - SET_STR - IP_STR - "Next hop address\n" - "IP address of next hop\n") -{ - union sockunion su; - int ret; + route_map_match_interface_hook (generic_match_add); + route_map_no_match_interface_hook (generic_match_delete); - ret = str2sockunion (argv[0], &su); - if (ret < 0) - { - vty_out (vty, "%% Malformed next-hop address%s", VTY_NEWLINE); - return CMD_WARNING; - } - if (su.sin.sin_addr.s_addr == 0 || - IPV4_CLASS_DE(su.sin.sin_addr.s_addr)) - { - vty_out (vty, "%% nexthop address cannot be 0.0.0.0, multicast " - "or reserved%s", VTY_NEWLINE); - return CMD_WARNING; - } + route_map_match_ip_address_hook (generic_match_add); + route_map_no_match_ip_address_hook (generic_match_delete); - return rip_route_set_add (vty, vty->index, "ip next-hop", argv[0]); -} + route_map_match_ip_address_prefix_list_hook (generic_match_add); + route_map_no_match_ip_address_prefix_list_hook (generic_match_delete); -DEFUN (no_set_ip_nexthop, - no_set_ip_nexthop_cmd, - "no set ip next-hop", - NO_STR - SET_STR - IP_STR - "Next hop address\n") -{ - if (argc == 0) - return rip_route_set_delete (vty, vty->index, "ip next-hop", NULL); - - return rip_route_set_delete (vty, vty->index, "ip next-hop", argv[0]); -} + route_map_match_ip_next_hop_hook (generic_match_add); + route_map_no_match_ip_next_hop_hook (generic_match_delete); -ALIAS (no_set_ip_nexthop, - no_set_ip_nexthop_val_cmd, - "no set ip next-hop A.B.C.D", - NO_STR - SET_STR - IP_STR - "Next hop address\n" - "IP address of next hop\n") - -DEFUN (set_tag, - set_tag_cmd, - "set tag <1-4294967295>", - SET_STR - "Tag value for routing protocol\n" - "Tag value\n") -{ - return rip_route_set_add (vty, vty->index, "tag", argv[0]); -} + route_map_match_ip_next_hop_prefix_list_hook (generic_match_add); + route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete); -DEFUN (no_set_tag, - no_set_tag_cmd, - "no set tag", - NO_STR - SET_STR - "Tag value for routing protocol\n") -{ - if (argc == 0) - return rip_route_set_delete (vty, vty->index, "tag", NULL); - - return rip_route_set_delete (vty, vty->index, "tag", argv[0]); -} + route_map_match_metric_hook (generic_match_add); + route_map_no_match_metric_hook (generic_match_delete); -ALIAS (no_set_tag, - no_set_tag_val_cmd, - "no set tag <1-4294967295>", - NO_STR - SET_STR - "Tag value for routing protocol\n" - "Tag value\n") + route_map_match_tag_hook (generic_match_add); + route_map_no_match_tag_hook (generic_match_delete); -void -rip_route_map_reset () -{ - ; -} + route_map_set_ip_nexthop_hook (generic_set_add); + route_map_no_set_ip_nexthop_hook (generic_set_delete); -/* Route-map init */ -void -rip_route_map_init () -{ - route_map_init (); + route_map_set_metric_hook (generic_set_add); + route_map_no_set_metric_hook (generic_set_delete); - route_map_add_hook (rip_route_map_update); - route_map_delete_hook (rip_route_map_update); + route_map_set_tag_hook (generic_set_add); + route_map_no_set_tag_hook (generic_set_delete); route_map_install_match (&route_match_metric_cmd); route_map_install_match (&route_match_interface_cmd); diff --cc ripngd/ripng_routemap.c index 61900408ff,19fa70227d..7cab5861bf --- a/ripngd/ripng_routemap.c +++ b/ripngd/ripng_routemap.c @@@ -385,26 -683,7 +385,25 @@@ voi ripng_route_map_init () { route_map_init (); - route_map_init_vty (); + route_map_match_interface_hook (generic_match_add); + route_map_no_match_interface_hook (generic_match_delete); + + route_map_match_metric_hook (generic_match_add); + route_map_no_match_metric_hook (generic_match_delete); + + route_map_match_tag_hook (generic_match_add); + route_map_no_match_tag_hook (generic_match_delete); + + route_map_set_ipv6_nexthop_local_hook (generic_set_add); + route_map_no_set_ipv6_nexthop_local_hook (generic_set_delete); + + route_map_set_metric_hook (generic_set_add); + route_map_no_set_metric_hook (generic_set_delete); + + route_map_set_tag_hook (generic_set_add); + route_map_no_set_tag_hook (generic_set_delete); + route_map_install_match (&route_match_metric_cmd); route_map_install_match (&route_match_interface_cmd); route_map_install_match (&route_match_tag_cmd); diff --cc zebra/if_netlink.c index 09268d3518,c44219a495..f7f6334a77 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@@ -21,10 -21,764 +21,765 @@@ */ #include + #include + + #include "linklist.h" + #include "if.h" + #include "log.h" + #include "prefix.h" + #include "connected.h" + #include "table.h" + #include "memory.h" + #include "zebra_memory.h" + #include "rib.h" + #include "thread.h" + #include "privs.h" + #include "nexthop.h" + #include "vrf.h" + #include "mpls.h" +#include "vty.h" #include "zebra/zserv.h" - #include "zebra/rt_netlink.h" + #include "zebra/zebra_ns.h" + #include "zebra/zebra_vrf.h" + #include "zebra/rt.h" + #include "zebra/redistribute.h" + #include "zebra/interface.h" + #include "zebra/debug.h" + #include "zebra/rtadv.h" + #include "zebra/zebra_ptm.h" + #include "zebra/zebra_mpls.h" + #include "zebra/kernel_netlink.h" + #include "zebra/if_netlink.h" + + + /* Note: on netlink systems, there should be a 1-to-1 mapping between interface + names and ifindex values. */ + static void + set_ifindex(struct interface *ifp, ifindex_t ifi_index, struct zebra_ns *zns) + { + struct interface *oifp; + + if (((oifp = if_lookup_by_index_per_ns (zns, ifi_index)) != NULL) && (oifp != ifp)) + { + if (ifi_index == IFINDEX_INTERNAL) + zlog_err("Netlink is setting interface %s ifindex to reserved " + "internal value %u", ifp->name, ifi_index); + else + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("interface index %d was renamed from %s to %s", + ifi_index, oifp->name, ifp->name); + if (if_is_up(oifp)) + zlog_err("interface rename detected on up interface: index %d " + "was renamed from %s to %s, results are uncertain!", + ifi_index, oifp->name, ifp->name); + if_delete_update(oifp); + } + } + ifp->ifindex = ifi_index; + } + + /* Utility function to parse hardware link-layer address and update ifp */ + static void + netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp) + { + int i; + + if (tb[IFLA_ADDRESS]) + { + int hw_addr_len; + + hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]); + + if (hw_addr_len > INTERFACE_HWADDR_MAX) + zlog_warn ("Hardware address is too large: %d", hw_addr_len); + else + { + ifp->hw_addr_len = hw_addr_len; + memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len); + + for (i = 0; i < hw_addr_len; i++) + if (ifp->hw_addr[i] != 0) + break; + + if (i == hw_addr_len) + ifp->hw_addr_len = 0; + else + ifp->hw_addr_len = hw_addr_len; + } + } + } + + static enum zebra_link_type + netlink_to_zebra_link_type (unsigned int hwt) + { + switch (hwt) + { + case ARPHRD_ETHER: return ZEBRA_LLT_ETHER; + case ARPHRD_EETHER: return ZEBRA_LLT_EETHER; + case ARPHRD_AX25: return ZEBRA_LLT_AX25; + case ARPHRD_PRONET: return ZEBRA_LLT_PRONET; + case ARPHRD_IEEE802: return ZEBRA_LLT_IEEE802; + case ARPHRD_ARCNET: return ZEBRA_LLT_ARCNET; + case ARPHRD_APPLETLK: return ZEBRA_LLT_APPLETLK; + case ARPHRD_DLCI: return ZEBRA_LLT_DLCI; + case ARPHRD_ATM: return ZEBRA_LLT_ATM; + case ARPHRD_METRICOM: return ZEBRA_LLT_METRICOM; + case ARPHRD_IEEE1394: return ZEBRA_LLT_IEEE1394; + case ARPHRD_EUI64: return ZEBRA_LLT_EUI64; + case ARPHRD_INFINIBAND: return ZEBRA_LLT_INFINIBAND; + case ARPHRD_SLIP: return ZEBRA_LLT_SLIP; + case ARPHRD_CSLIP: return ZEBRA_LLT_CSLIP; + case ARPHRD_SLIP6: return ZEBRA_LLT_SLIP6; + case ARPHRD_CSLIP6: return ZEBRA_LLT_CSLIP6; + case ARPHRD_RSRVD: return ZEBRA_LLT_RSRVD; + case ARPHRD_ADAPT: return ZEBRA_LLT_ADAPT; + case ARPHRD_ROSE: return ZEBRA_LLT_ROSE; + case ARPHRD_X25: return ZEBRA_LLT_X25; + case ARPHRD_PPP: return ZEBRA_LLT_PPP; + case ARPHRD_CISCO: return ZEBRA_LLT_CHDLC; + case ARPHRD_LAPB: return ZEBRA_LLT_LAPB; + case ARPHRD_RAWHDLC: return ZEBRA_LLT_RAWHDLC; + case ARPHRD_TUNNEL: return ZEBRA_LLT_IPIP; + case ARPHRD_TUNNEL6: return ZEBRA_LLT_IPIP6; + case ARPHRD_FRAD: return ZEBRA_LLT_FRAD; + case ARPHRD_SKIP: return ZEBRA_LLT_SKIP; + case ARPHRD_LOOPBACK: return ZEBRA_LLT_LOOPBACK; + case ARPHRD_LOCALTLK: return ZEBRA_LLT_LOCALTLK; + case ARPHRD_FDDI: return ZEBRA_LLT_FDDI; + case ARPHRD_SIT: return ZEBRA_LLT_SIT; + case ARPHRD_IPDDP: return ZEBRA_LLT_IPDDP; + case ARPHRD_IPGRE: return ZEBRA_LLT_IPGRE; + case ARPHRD_PIMREG: return ZEBRA_LLT_PIMREG; + case ARPHRD_HIPPI: return ZEBRA_LLT_HIPPI; + case ARPHRD_ECONET: return ZEBRA_LLT_ECONET; + case ARPHRD_IRDA: return ZEBRA_LLT_IRDA; + case ARPHRD_FCPP: return ZEBRA_LLT_FCPP; + case ARPHRD_FCAL: return ZEBRA_LLT_FCAL; + case ARPHRD_FCPL: return ZEBRA_LLT_FCPL; + case ARPHRD_FCFABRIC: return ZEBRA_LLT_FCFABRIC; + case ARPHRD_IEEE802_TR: return ZEBRA_LLT_IEEE802_TR; + case ARPHRD_IEEE80211: return ZEBRA_LLT_IEEE80211; + case ARPHRD_IEEE802154: return ZEBRA_LLT_IEEE802154; + #ifdef ARPHRD_IP6GRE + case ARPHRD_IP6GRE: return ZEBRA_LLT_IP6GRE; + #endif + #ifdef ARPHRD_IEEE802154_PHY + case ARPHRD_IEEE802154_PHY: return ZEBRA_LLT_IEEE802154_PHY; + #endif + + default: return ZEBRA_LLT_UNKNOWN; + } + } + + #define parse_rtattr_nested(tb, max, rta) \ + netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) + + static void + netlink_vrf_change (struct nlmsghdr *h, struct rtattr *tb, const char *name) + { + struct ifinfomsg *ifi; + struct rtattr *linkinfo[IFLA_INFO_MAX+1]; + struct rtattr *attr[IFLA_VRF_MAX+1]; + struct vrf *vrf; + struct zebra_vrf *zvrf; + u_int32_t nl_table_id; + + ifi = NLMSG_DATA (h); + + memset (linkinfo, 0, sizeof linkinfo); + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); + + if (!linkinfo[IFLA_INFO_DATA]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: IFLA_INFO_DATA missing from VRF message: %s", __func__, name); + return; + } + + memset (attr, 0, sizeof attr); + parse_rtattr_nested(attr, IFLA_VRF_MAX, linkinfo[IFLA_INFO_DATA]); + if (!attr[IFLA_VRF_TABLE]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: IFLA_VRF_TABLE missing from VRF message: %s", __func__, name); + return; + } + + nl_table_id = *(u_int32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]); + + if (h->nlmsg_type == RTM_NEWLINK) + { + /* If VRF already exists, we just return; status changes are handled + * against the VRF "interface". + */ + vrf = vrf_lookup ((vrf_id_t)ifi->ifi_index); + if (vrf && vrf->info) + return; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("RTM_NEWLINK for VRF %s(%u) table %u", + name, ifi->ifi_index, nl_table_id); + + /* + * vrf_get is implied creation if it does not exist + */ + vrf = vrf_get((vrf_id_t)ifi->ifi_index, name); // It would create vrf + if (!vrf) + { + zlog_err ("VRF %s id %u not created", name, ifi->ifi_index); + return; + } + + /* Enable the created VRF. */ + if (!vrf_enable (vrf)) + { + zlog_err ("Failed to enable VRF %s id %u", name, ifi->ifi_index); + return; + } + + /* + * This is the only place that we get the actual kernel table_id + * being used. We need it to set the table_id of the routes + * we are passing to the kernel.... And to throw some totally + * awesome parties. that too. + */ + zvrf = (struct zebra_vrf *)vrf->info; + zvrf->table_id = nl_table_id; + } + else //h->nlmsg_type == RTM_DELLINK + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("RTM_DELLINK for VRF %s(%u)", name, ifi->ifi_index); + + vrf = vrf_lookup ((vrf_id_t)ifi->ifi_index); + + if (!vrf) + { + zlog_warn ("%s: vrf not found", __func__); + return; + } + + vrf_delete (vrf); + } + } + + /* Called from interface_lookup_netlink(). This function is only used + during bootstrap. */ + static int + netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id) + { + int len; + struct ifinfomsg *ifi; + struct rtattr *tb[IFLA_MAX + 1]; + struct rtattr *linkinfo[IFLA_MAX + 1]; + struct interface *ifp; + char *name = NULL; + char *kind = NULL; + char *slave_kind = NULL; + int vrf_device = 0; + struct zebra_ns *zns; + vrf_id_t vrf_id = VRF_DEFAULT; + + zns = zebra_ns_lookup (ns_id); + ifi = NLMSG_DATA (h); + + if (h->nlmsg_type != RTM_NEWLINK) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg)); + if (len < 0) + return -1; + + if (ifi->ifi_family == AF_BRIDGE) + return 0; + + /* Looking up interface name. */ + memset (tb, 0, sizeof tb); + netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); + + #ifdef IFLA_WIRELESS + /* check for wireless messages to ignore */ + if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__); + return 0; + } + #endif /* IFLA_WIRELESS */ + + if (tb[IFLA_IFNAME] == NULL) + return -1; + name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + + if (tb[IFLA_LINKINFO]) + { + memset (linkinfo, 0, sizeof linkinfo); + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + + if (linkinfo[IFLA_INFO_KIND]) + kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); + + #if HAVE_DECL_IFLA_INFO_SLAVE_KIND + if (linkinfo[IFLA_INFO_SLAVE_KIND]) + slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); + #endif + + if (kind && strcmp(kind, "vrf") == 0) + { + vrf_device = 1; + netlink_vrf_change(h, tb[IFLA_LINKINFO], name); + vrf_id = (vrf_id_t)ifi->ifi_index; + } + } + + if (tb[IFLA_MASTER]) + { + if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) + vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); + } + + /* Add interface. */ + ifp = if_get_by_name_vrf (name, vrf_id); + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (vrf_device) + SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); + ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); + ifp->metric = 0; + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + + /* Hardware type and address. */ + ifp->ll_type = netlink_to_zebra_link_type (ifi->ifi_type); + netlink_interface_update_hw_addr (tb, ifp); + + if_add_update (ifp); + + return 0; + } + + /* Interface lookup by netlink socket. */ + int + interface_lookup_netlink (struct zebra_ns *zns) + { + int ret; + + /* Get interface information. */ + ret = netlink_request (AF_PACKET, RTM_GETLINK, &zns->netlink_cmd); + if (ret < 0) + return ret; + ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0); + if (ret < 0) + return ret; + + /* Get IPv4 address of the interfaces. */ + ret = netlink_request (AF_INET, RTM_GETADDR, &zns->netlink_cmd); + if (ret < 0) + return ret; + ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0); + if (ret < 0) + return ret; + + #ifdef HAVE_IPV6 + /* Get IPv6 address of the interfaces. */ + ret = netlink_request (AF_INET6, RTM_GETADDR, &zns->netlink_cmd); + if (ret < 0) + return ret; + ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0); + if (ret < 0) + return ret; + #endif /* HAVE_IPV6 */ + + return 0; + } + + /* Interface address modification. */ + static int + netlink_address (int cmd, int family, struct interface *ifp, + struct connected *ifc) + { + int bytelen; + struct prefix *p; + + struct + { + struct nlmsghdr n; + struct ifaddrmsg ifa; + char buf[NL_PKT_BUF_SIZE]; + } req; + + struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); + + p = ifc->address; + memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); + + bytelen = (family == AF_INET ? 4 : 16); + + req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = cmd; + req.ifa.ifa_family = family; + + req.ifa.ifa_index = ifp->ifindex; + req.ifa.ifa_prefixlen = p->prefixlen; + + addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen); + + if (family == AF_INET && cmd == RTM_NEWADDR) + { + if (!CONNECTED_PEER(ifc) && ifc->destination) + { + p = ifc->destination; + addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, + bytelen); + } + } + + if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY)) + SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY); + + if (ifc->label) + addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, + strlen (ifc->label) + 1); + + return netlink_talk (&req.n, &zns->netlink_cmd, zns); + } + + int + kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc) + { + return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc); + } + + int + kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc) + { + return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc); + } + + int + netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id) + { + int len; + struct ifaddrmsg *ifa; + struct rtattr *tb[IFA_MAX + 1]; + struct interface *ifp; + void *addr; + void *broad; + u_char flags = 0; + char *label = NULL; + struct zebra_ns *zns; + + zns = zebra_ns_lookup (ns_id); + ifa = NLMSG_DATA (h); + + if (ifa->ifa_family != AF_INET + #ifdef HAVE_IPV6 + && ifa->ifa_family != AF_INET6 + #endif /* HAVE_IPV6 */ + ) + return 0; + + if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg)); + if (len < 0) + return -1; + + memset (tb, 0, sizeof tb); + netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len); + + ifp = if_lookup_by_index_per_ns (zns, ifa->ifa_index); + if (ifp == NULL) + { + zlog_err ("netlink_interface_addr can't find interface by index %d", + ifa->ifa_index); + return -1; + } + + if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ + { + char buf[BUFSIZ]; + zlog_debug ("netlink_interface_addr %s %s flags 0x%x:", + nl_msg_type_to_str (h->nlmsg_type), ifp->name, + ifa->ifa_flags); + if (tb[IFA_LOCAL]) + zlog_debug (" IFA_LOCAL %s/%d", + inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]), + buf, BUFSIZ), ifa->ifa_prefixlen); + if (tb[IFA_ADDRESS]) + zlog_debug (" IFA_ADDRESS %s/%d", + inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]), + buf, BUFSIZ), ifa->ifa_prefixlen); + if (tb[IFA_BROADCAST]) + zlog_debug (" IFA_BROADCAST %s/%d", + inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]), + buf, BUFSIZ), ifa->ifa_prefixlen); + if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL]))) + zlog_debug (" IFA_LABEL %s", (char *)RTA_DATA (tb[IFA_LABEL])); + + if (tb[IFA_CACHEINFO]) + { + struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]); + zlog_debug (" IFA_CACHEINFO pref %d, valid %d", + ci->ifa_prefered, ci->ifa_valid); + } + } + + /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */ + if (tb[IFA_LOCAL] == NULL) + tb[IFA_LOCAL] = tb[IFA_ADDRESS]; + if (tb[IFA_ADDRESS] == NULL) + tb[IFA_ADDRESS] = tb[IFA_LOCAL]; + + /* local interface address */ + addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL); + + /* is there a peer address? */ + if (tb[IFA_ADDRESS] && + memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS]))) + { + broad = RTA_DATA(tb[IFA_ADDRESS]); + SET_FLAG (flags, ZEBRA_IFA_PEER); + } + else + /* seeking a broadcast address */ + broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL); + + /* addr is primary key, SOL if we don't have one */ + if (addr == NULL) + { + zlog_debug ("%s: NULL address", __func__); + return -1; + } + + /* Flags. */ + if (ifa->ifa_flags & IFA_F_SECONDARY) + SET_FLAG (flags, ZEBRA_IFA_SECONDARY); + + /* Label */ + if (tb[IFA_LABEL]) + label = (char *) RTA_DATA (tb[IFA_LABEL]); + + if (ifp && label && strcmp (ifp->name, label) == 0) + label = NULL; + + /* Register interface address to the interface. */ + if (ifa->ifa_family == AF_INET) + { + if (h->nlmsg_type == RTM_NEWADDR) + connected_add_ipv4 (ifp, flags, + (struct in_addr *) addr, ifa->ifa_prefixlen, + (struct in_addr *) broad, label); + else + connected_delete_ipv4 (ifp, flags, + (struct in_addr *) addr, ifa->ifa_prefixlen, + (struct in_addr *) broad); + } + #ifdef HAVE_IPV6 + if (ifa->ifa_family == AF_INET6) + { + if (h->nlmsg_type == RTM_NEWADDR) + { + /* Only consider valid addresses; we'll not get a notification from + * the kernel till IPv6 DAD has completed, but at init time, Quagga + * does query for and will receive all addresses. + */ + if (!(ifa->ifa_flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))) + connected_add_ipv6 (ifp, flags, (struct in6_addr *) addr, + ifa->ifa_prefixlen, (struct in6_addr *) broad, label); + } + else + connected_delete_ipv6 (ifp, + (struct in6_addr *) addr, ifa->ifa_prefixlen, + (struct in6_addr *) broad); + } + #endif /* HAVE_IPV6 */ + + return 0; + } + + int + netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id) + { + int len; + struct ifinfomsg *ifi; + struct rtattr *tb[IFLA_MAX + 1]; + struct rtattr *linkinfo[IFLA_MAX + 1]; + struct interface *ifp; + char *name = NULL; + char *kind = NULL; + char *slave_kind = NULL; + int vrf_device = 0; + struct zebra_ns *zns; + vrf_id_t vrf_id = VRF_DEFAULT; + + zns = zebra_ns_lookup (ns_id); + ifi = NLMSG_DATA (h); + + if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) + { + /* If this is not link add/delete message so print warning. */ + zlog_warn ("netlink_link_change: wrong kernel message %d", + h->nlmsg_type); + return 0; + } + + len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg)); + if (len < 0) + return -1; + + if (ifi->ifi_family == AF_BRIDGE) + return 0; + + /* Looking up interface name. */ + memset (tb, 0, sizeof tb); + netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); + + #ifdef IFLA_WIRELESS + /* check for wireless messages to ignore */ + if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__); + return 0; + } + #endif /* IFLA_WIRELESS */ + + if (tb[IFLA_IFNAME] == NULL) + return -1; + name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + + if (tb[IFLA_LINKINFO]) + { + memset (linkinfo, 0, sizeof linkinfo); + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + + if (linkinfo[IFLA_INFO_KIND]) + kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); + + #if HAVE_DECL_IFLA_INFO_SLAVE_KIND + if (linkinfo[IFLA_INFO_SLAVE_KIND]) + slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); + #endif + + if (kind && strcmp(kind, "vrf") == 0) + { + vrf_device = 1; + netlink_vrf_change(h, tb[IFLA_LINKINFO], name); + vrf_id = (vrf_id_t)ifi->ifi_index; + } + } + + /* See if interface is present. */ + ifp = if_lookup_by_index_per_ns (zns, ifi->ifi_index); + + if (h->nlmsg_type == RTM_NEWLINK) + { + if (tb[IFLA_MASTER]) + { + if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) + vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); + } + + if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) + { + /* Add interface notification from kernel */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("RTM_NEWLINK for %s(%u) (ifp %p) vrf_id %u flags 0x%x", + name, ifi->ifi_index, ifp, vrf_id, ifi->ifi_flags); + + if (ifp == NULL) + { + /* unknown interface */ + ifp = if_get_by_name_vrf (name, vrf_id); + } + else + { + /* pre-configured interface, learnt now */ + if (ifp->vrf_id != vrf_id) + if_update_vrf (ifp, name, strlen(name), vrf_id); + } + + /* Update interface information. */ + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (vrf_device) + SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); + ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); + ifp->metric = 0; + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + + netlink_interface_update_hw_addr (tb, ifp); + + /* Inform clients, install any configured addresses. */ + if_add_update (ifp); + } + else if (ifp->vrf_id != vrf_id) + { + /* VRF change for an interface. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("RTM_NEWLINK vrf-change for %s(%u) " + "vrf_id %u -> %u flags 0x%x", + name, ifp->ifindex, ifp->vrf_id, + vrf_id, ifi->ifi_flags); + + if_handle_vrf_change (ifp, vrf_id); + } + else + { + /* Interface status change. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("RTM_NEWLINK status for %s(%u) flags 0x%x", + name, ifp->ifindex, ifi->ifi_flags); + + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); + ifp->metric = 0; + + netlink_interface_update_hw_addr (tb, ifp); + + if (if_is_no_ptm_operative (ifp)) + { + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (!if_is_no_ptm_operative (ifp)) + if_down (ifp); + else if (if_is_operative (ifp)) + /* Must notify client daemons of new interface status. */ + zebra_interface_up_update (ifp); + } + else + { + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (if_is_operative (ifp)) + if_up (ifp); + } + } + } + else + { + /* Delete interface notification from kernel */ + if (ifp == NULL) + { + zlog_warn ("RTM_DELLINK for unknown interface %s(%u)", + name, ifi->ifi_index); + return 0; + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("RTM_DELLINK for %s(%u)", name, ifp->ifindex); + + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); + + if (!vrf_device) + if_delete_update (ifp); + } + + return 0; + } /* Interface information read by netlink. */ void diff --cc zebra/rt_netlink.c index afcd5f0235,f16fd55c98..90d71e6351 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@@ -1178,7 -312,8 +313,7 @@@ netlink_route_change (struct sockaddr_n struct rtattr *tb[RTA_MAX + 1]; u_char zebra_flags = 0; struct prefix p; - + vrf_id_t vrf_id = VRF_DEFAULT; - char anyaddr[16] = { 0 }; int index; diff --cc zebra/zebra_fpm_netlink.c index c5a6a49691,6543298605..f2cba10943 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@@ -27,15 -27,15 +27,16 @@@ #include "log.h" #include "rib.h" +#include "vty.h" - #include "zserv.h" - #include "zebra_ns.h" - #include "zebra_vrf.h" - #include "rt_netlink.h" + #include "zebra/zserv.h" + #include "zebra/zebra_ns.h" + #include "zebra/zebra_vrf.h" + #include "zebra/kernel_netlink.h" + #include "zebra/rt_netlink.h" #include "nexthop.h" - #include "zebra_fpm_private.h" + #include "zebra/zebra_fpm_private.h" /* * addr_to_a diff --cc zebra/zebra_routemap.c index 9b407ed392,21fd6a4db9..59725561f5 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@@ -1462,21 -1788,29 +1462,20 @@@ zebra_route_map_init ( { install_element (CONFIG_NODE, &ip_protocol_cmd); install_element (CONFIG_NODE, &no_ip_protocol_cmd); - install_element (CONFIG_NODE, &no_ip_protocol_val_cmd); install_element (VIEW_NODE, &show_ip_protocol_cmd); - install_element (ENABLE_NODE, &show_ip_protocol_cmd); install_element (CONFIG_NODE, &ipv6_protocol_cmd); install_element (CONFIG_NODE, &no_ipv6_protocol_cmd); - install_element (CONFIG_NODE, &no_ipv6_protocol_val_cmd); install_element (VIEW_NODE, &show_ipv6_protocol_cmd); - install_element (ENABLE_NODE, &show_ipv6_protocol_cmd); install_element (CONFIG_NODE, &ip_protocol_nht_rmap_cmd); install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd); - install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_val_cmd); install_element (VIEW_NODE, &show_ip_protocol_nht_cmd); - install_element (ENABLE_NODE, &show_ip_protocol_nht_cmd); install_element (CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd); install_element (CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd); - install_element (CONFIG_NODE, &no_ipv6_protocol_nht_rmap_val_cmd); install_element (VIEW_NODE, &show_ipv6_protocol_nht_cmd); - install_element (ENABLE_NODE, &show_ipv6_protocol_nht_cmd); install_element (CONFIG_NODE, &zebra_route_map_timer_cmd); install_element (CONFIG_NODE, &no_zebra_route_map_timer_cmd); - install_element (CONFIG_NODE, &no_zebra_route_map_timer_val_cmd); route_map_init (); - route_map_init_vty (); route_map_add_hook (zebra_route_map_add); route_map_delete_hook (zebra_route_map_delete);