static int
peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi,
- safi_t safi, int v6only, const char *peer_group_name)
+ safi_t safi, int v6only, const char *peer_group_name,
+ const char *as_str)
{
- as_t as;
+ as_t as = 0;
+ int as_type = AS_UNSPECIFIED;
struct bgp *bgp;
struct peer *peer;
struct peer_group *group;
return CMD_WARNING;
}
+ if (as_str)
+ {
+ if (strncmp(as_str, "internal", strlen("internal")) == 0)
+ {
+ as_type = AS_INTERNAL;
+ }
+ else if (strncmp(as_str, "external", strlen("external")) == 0)
+ {
+ as_type = AS_EXTERNAL;
+ }
+ else
+ {
+ /* Get AS number. */
+ VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, BGP_AS4_MAX);
+ as_type = AS_SPECIFIED;
+ }
+ }
+
peer = peer_lookup_by_conf_if (bgp, conf_if);
if (!peer)
{
if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
&& afi == AFI_IP && safi == SAFI_UNICAST)
- peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, AS_UNSPECIFIED, 0, 0, NULL);
+ peer = peer_create (NULL, conf_if, bgp, bgp->as, as, as_type, 0, 0,
+ NULL);
else
- peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, AS_UNSPECIFIED, afi, safi, NULL);
+ peer = peer_create (NULL, conf_if, bgp, bgp->as, as, as_type, afi, safi,
+ NULL);
if (peer && v6only)
SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
* gets deleted later etc.)
*/
if (peer->ifp)
- bgp_zebra_initiate_radv (bgp, peer);
+ {
+ bgp_zebra_initiate_radv (bgp, peer);
+ }
+ peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE);
}
else if ((v6only && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) ||
(!v6only && CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)))
"Enable BGP on interface\n")
{
if (argc == 2)
- return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, argv[1]);
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0,
+ argv[1], NULL);
else
- return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0, NULL);
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0,
+ NULL, NULL);
}
ALIAS (neighbor_interface_config,
"Enable BGP with v6 link-local only\n")
{
if (argc == 2)
- return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, argv[1]);
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1,
+ argv[1], NULL);
else
- return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1, NULL);
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1,
+ NULL, NULL);
}
ALIAS (neighbor_interface_config_v6only,
"Member of the peer-group\n"
"peer-group name\n")
+DEFUN (neighbor_interface_config_remote_as,
+ neighbor_interface_config_remote_as_cmd,
+ "neighbor WORD interface remote-as (" CMD_AS_RANGE "|external|internal)",
+ NEIGHBOR_STR
+ "Interface name or neighbor tag\n"
+ "Enable BGP on interface\n"
+ AS_STR)
+{
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 0,
+ NULL, argv[1]);
+}
+
+DEFUN (neighbor_interface_v6only_config_remote_as,
+ neighbor_interface_v6only_config_remote_as_cmd,
+ "neighbor WORD interface v6only remote-as (" CMD_AS_RANGE "|external|internal)",
+ NEIGHBOR_STR
+ "Interface name or neighbor tag\n"
+ "Enable BGP on interface\n"
+ AS_STR)
+{
+ return peer_conf_interface_get (vty, argv[0], AFI_IP, SAFI_UNICAST, 1,
+ NULL, argv[1]);
+}
+
DEFUN (neighbor_peer_group,
neighbor_peer_group_cmd,
"neighbor WORD peer-group",
"Member of the peer-group\n"
"peer-group name\n")
+ALIAS (no_neighbor_interface_config,
+ no_neighbor_interface_config_remote_as_cmd,
+ "no neighbor WORD interface remote-as (" CMD_AS_RANGE "|internal|external)",
+ NO_STR
+ NEIGHBOR_STR
+ "Interface name\n"
+ "Configure BGP on interface\n"
+ AS_STR)
+
+ALIAS (no_neighbor_interface_config,
+ no_neighbor_interface_config_v6only_remote_as_cmd,
+ "no neighbor WORD interface v6only remote-as (" CMD_AS_RANGE "|internal|external)",
+ NO_STR
+ NEIGHBOR_STR
+ "Interface name\n"
+ "Configure BGP on interface\n"
+ "Enable BGP with v6 link-local only\n"
+ AS_STR)
DEFUN (no_neighbor_peer_group,
no_neighbor_peer_group_cmd,
install_element (BGP_NODE, &neighbor_interface_config_v6only_cmd);
install_element (BGP_NODE, &neighbor_interface_config_peergroup_cmd);
install_element (BGP_NODE, &neighbor_interface_config_v6only_peergroup_cmd);
+ install_element (BGP_NODE, &neighbor_interface_config_remote_as_cmd);
+ install_element (BGP_NODE, &neighbor_interface_v6only_config_remote_as_cmd);
install_element (BGP_NODE, &no_neighbor_cmd);
install_element (BGP_NODE, &no_neighbor_remote_as_cmd);
install_element (BGP_NODE, &no_neighbor_interface_config_cmd);
install_element (BGP_NODE, &no_neighbor_interface_config_v6only_cmd);
install_element (BGP_NODE, &no_neighbor_interface_config_peergroup_cmd);
install_element (BGP_NODE, &no_neighbor_interface_config_v6only_peergroup_cmd);
+ install_element (BGP_NODE, &no_neighbor_interface_config_remote_as_cmd);
+ install_element (BGP_NODE, &no_neighbor_interface_config_v6only_remote_as_cmd);
/* "neighbor peer-group" commands. */
install_element (BGP_NODE, &neighbor_peer_group_cmd);
int first_member = 0;
afi_t afi;
safi_t safi;
+ int cap_enhe_preset = 0;
/* Lookup the peer. */
if (!peer)
first_member = 1;
}
+ if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ cap_enhe_preset = 1;
+
peer_group2peer_config_copy(group, peer);
+ /*
+ * Capability extended-nexthop is enabled for an interface neighbor by
+ * default. So, fix that up here.
+ */
+ if (peer->ifp && cap_enhe_preset)
+ peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE);
+
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
{
struct peer *g_peer = NULL;
char buf[SU_ADDRSTRLEN];
char *addr;
+ int if_pg_printed = FALSE;
+ int if_ras_printed = FALSE;
/* Skip dynamic neighbors. */
if (peer_dynamic_neighbor (peer))
vty_out (vty, " neighbor %s interface", addr);
if (peer_group_active (peer))
- vty_out (vty, " peer-group %s", peer->group->name);
+ {
+ vty_out (vty, " peer-group %s", peer->group->name);
+ if_pg_printed = TRUE;
+ }
+ else if (peer->as_type == AS_SPECIFIED)
+ {
+ vty_out (vty, " remote-as %u", peer->as);
+ if_ras_printed = TRUE;
+ }
+ else if (peer->as_type == AS_INTERNAL)
+ {
+ vty_out (vty, " remote-as internal");
+ if_ras_printed = TRUE;
+ }
+ else if (peer->as_type == AS_EXTERNAL)
+ {
+ vty_out (vty, " remote-as external");
+ if_ras_printed = TRUE;
+ }
vty_out (vty, "%s", VTY_NEWLINE);
}
{
g_peer = peer->group->conf;
- if (g_peer->as_type == AS_UNSPECIFIED)
+ if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed)
{
if (peer->as_type == AS_SPECIFIED)
{
/* For swpX peers we displayed the peer-group
* via 'neighbor swpX interface peer-group WORD' */
- if (!peer->conf_if)
+ if (!if_pg_printed)
vty_out (vty, " neighbor %s peer-group %s%s", addr,
peer->group->name, VTY_NEWLINE);
}
VTY_NEWLINE);
}
- if (peer->as_type == AS_SPECIFIED)
- {
- vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
- VTY_NEWLINE);
- }
- else if (peer->as_type == AS_INTERNAL)
- {
- vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
- }
- else if (peer->as_type == AS_EXTERNAL)
+ if (!if_ras_printed)
{
- vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
+ if (peer->as_type == AS_SPECIFIED)
+ {
+ vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
+ VTY_NEWLINE);
+ }
+ else if (peer->as_type == AS_INTERNAL)
+ {
+ vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
+ }
+ else if (peer->as_type == AS_EXTERNAL)
+ {
+ vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
+ }
}
}
}
/* capability extended-nexthop */
- if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ if (peer->ifp && !CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ {
+ if (! peer_group_active (peer) ||
+ ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ {
+ vty_out (vty, " no neighbor %s capability extended-nexthop%s", addr,
+ VTY_NEWLINE);
+ }
+ }
+
+ if (!peer->ifp && CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
{
if (! peer_group_active (peer) ||
! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE))
lines_to_add_to_del.append((ctx_keys, swpx_interface))
lines_to_add_to_del.append((tmp_ctx_keys, swpx_peergroup))
+ """
+ In 3.0.1 we changed how we display neighbor interface command. Older
+ versions of quagga would display the following:
+ neighbor swp1 interface
+ neighbor swp1 remote-as external
+ neighbor swp1 capability extended-nexthop
+
+ but today we display via a single line
+ neighbor swp1 interface remote-as external
+
+ and capability extended-nexthop is no longer needed because we
+ automatically enable it when the neighbor is of type interface.
+
+ This change confuses quagga-reload.py so check to see if we are deleting
+ neighbor swp1 interface remote-as (external|internal|ASNUM)
+
+ and adding
+ neighbor swp1 interface
+ neighbor swp1 remote-as (external|internal|ASNUM)
+ neighbor swp1 capability extended-nexthop
+
+ If so then chop the del line and the corresponding add lines
+ """
+ re_swpx_int_remoteas = re.search('neighbor (\S+) interface remote-as (\S+)', line)
+ re_swpx_int_v6only_remoteas = re.search('neighbor (\S+) interface v6only remote-as (\S+)', line)
+
+ if re_swpx_int_remoteas or re_swpx_int_v6only_remoteas:
+ swpx_interface = None
+ swpx_remoteas = None
+
+ if re_swpx_int_remoteas:
+ swpx = re_swpx_int_remoteas.group(1)
+ remoteas = re_swpx_int_remoteas.group(2)
+ swpx_interface = "neighbor %s interface" % swpx
+ elif re_swpx_int_v6only_remoteas:
+ swpx = re_swpx_int_v6only_remoteas.group(1)
+ remoteas = re_swpx_int_v6only_remoteas.group(2)
+ swpx_interface = "neighbor %s interface v6only" % swpx
+
+ swpx_remoteas = "neighbor %s remote-as %s" % (swpx, remoteas)
+ found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface)
+ found_add_swpx_remoteas = line_exist(lines_to_add, ctx_keys, swpx_remoteas)
+ tmp_ctx_keys = tuple(list(ctx_keys))
+
+ if found_add_swpx_interface and found_add_swpx_remoteas:
+ deleted = True
+ lines_to_del_to_del.append((ctx_keys, line))
+ lines_to_add_to_del.append((ctx_keys, swpx_interface))
+ lines_to_add_to_del.append((tmp_ctx_keys, swpx_remoteas))
+
if not deleted:
found_add_line = line_exist(lines_to_add, ctx_keys, line)