]> git.puffer.fish Git - mirror/frr.git/commitdiff
Simplify BGP unnumbered configuration by eliminating the unessential.
authorDinesh G Dutt <ddutt@cumulusnetworks.com>
Wed, 13 Jul 2016 22:31:27 +0000 (15:31 -0700)
committerDinesh G Dutt <ddutt@cumulusnetworks.com>
Sat, 16 Jul 2016 05:17:00 +0000 (22:17 -0700)
To make BGP configuration as simple as possible, assume the capability
extended-nexthop to be default for interface neighbors. Also allow the
ability to specify remote-as on the same line as neighbor interface to
make BGP unnumbered configuration a single line.

One corner case. This is the first feature for which the default for a
member is different from the default for a peer-group. Since advertising
the capability is only done for interface neighbors, the capability is
not set for the peer-group, but is automatically set for interface
neighbors that belong to that peer-group. So, if you want to disable the
advertisement of this capability for an interface neighbor, you must
do it per each interface neighbor.

The patch is more complicated than it needs to be due to the handling
of quagga reload and appropriate updates to the show running output.

Ticket: CM-11830
Reviewed By: CCR-4958
Testing Done: Usual coterie, including manual

(cherry picked from commit 347914a0a785993200cb04ae3cbf8ff9a9104d60)

bgpd/bgp_vty.c
bgpd/bgpd.c
tools/quagga-reload.py

index e62a225b0f9a96f59c963c24d7d4a4122d88bd4e..5a9d431d2ebb9ff589c4f9396ed1ea1ed7b6b8b3 100644 (file)
@@ -2834,9 +2834,11 @@ DEFUN (neighbor_remote_as,
 
 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;
@@ -2852,14 +2854,34 @@ peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi,
       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);
@@ -2870,7 +2892,10 @@ peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi,
        * 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)))
@@ -2917,9 +2942,11 @@ DEFUN (neighbor_interface_config,
        "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,
@@ -2940,9 +2967,11 @@ DEFUN (neighbor_interface_config_v6only,
        "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,
@@ -2955,6 +2984,30 @@ 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",
@@ -3105,6 +3158,24 @@ ALIAS (no_neighbor_interface_config,
        "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,
@@ -14596,12 +14667,16 @@ bgp_vty_init (void)
   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);
index 05f1751e53cead7ddcee45c6d8a0d5ec1e84009b..a06e95e244578750f20dbabc70a224ad72f235cd 100644 (file)
@@ -2546,6 +2546,7 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer,
   int first_member = 0;
   afi_t afi;
   safi_t safi;
+  int cap_enhe_preset = 0;
 
   /* Lookup the peer.  */
   if (!peer)
@@ -2580,8 +2581,18 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *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++)
           {
@@ -6269,6 +6280,8 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
   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))
@@ -6290,7 +6303,25 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
         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);
     }
@@ -6301,7 +6332,7 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
     {
       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)
             {
@@ -6320,7 +6351,7 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
 
       /* 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);
     }
@@ -6335,18 +6366,21 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
                    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);
+            }
         }
     }
 
@@ -6541,7 +6575,17 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
     }
 
   /* 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))
index 9650822d1e2cc7ac85485f959d692756e9af497f..22d44b3369e502fae1cb12870001b50697e73989 100755 (executable)
@@ -507,6 +507,56 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
                     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)