]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: bgpd-no-as.patch
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 01:04:25 +0000 (18:04 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 01:04:25 +0000 (18:04 -0700)
bgp: Fixup of the remote-as command to allow user to not have to enter an actual as number
Signed-off-by: Donald Sharp<sharpd@cumulusnetworks.com>
Reviewed-by:

bgpd/bgp_fsm.c
bgpd/bgp_network.c
bgpd/bgp_packet.c
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index 388b85b05182fa745ce16c398cbd096ef4bdccfd..6db94ff4f20af1e541a5fa765712d5864fbe0237 100644 (file)
@@ -137,6 +137,7 @@ peer_xfer_conn(struct peer *from_peer)
   stream_fifo_clean(peer->obuf);
   stream_fifo_clean(from_peer->obuf);
 
+  peer->as = from_peer->as;
   peer->v_holdtime = from_peer->v_holdtime;
   peer->v_keepalive = from_peer->v_keepalive;
   peer->v_asorig = from_peer->v_asorig;
index 3cf1d3b84c3b72611210d4b2cac23c46d1c17e67..fc4983a563314ad2af0c4d54bb6f06e09922def7 100644 (file)
@@ -310,7 +310,7 @@ bgp_accept (struct thread *thread)
   bgp_set_socket_ttl (peer1, bgp_sock);
 
   peer = peer_create (&su, peer1->conf_if, peer1->bgp, peer1->local_as,
-                     peer1->as, 0, 0);
+                     peer1->as, peer1->as_type, 0, 0);
 
   peer_xfer_config(peer, peer1);
   UNSET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE);
index 1a5e8855a11efd4c08211a375e55430ca3620ec5..af76f7d64cae85e6992785f0f2e5ce75befdb7bc 100644 (file)
@@ -1033,13 +1033,43 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
     }
 
   /* Check neighbor as number. */
-  if (remote_as != peer->as)
+  if (peer->as_type == AS_INTERNAL)
+    {
+      if (remote_as != peer->bgp->as)
+       {
+         if (bgp_debug_neighbor_events(peer))
+           zlog_debug ("%s bad OPEN, remote AS is %u, internal specified",
+                       peer->host, remote_as);
+         bgp_notify_send_with_data (peer,
+                                    BGP_NOTIFY_OPEN_ERR,
+                                    BGP_NOTIFY_OPEN_BAD_PEER_AS,
+                                    notify_data_remote_as, 2);
+         return -1;
+       }
+      peer->as = peer->local_as;
+    }
+  else if (peer->as_type == AS_EXTERNAL)
+    {
+      if (remote_as == peer->bgp->as)
+       {
+         if (bgp_debug_neighbor_events(peer))
+           zlog_debug ("%s bad OPEN, remote AS is %u, external specified",
+                       peer->host, remote_as);
+         bgp_notify_send_with_data (peer,
+                                    BGP_NOTIFY_OPEN_ERR,
+                                    BGP_NOTIFY_OPEN_BAD_PEER_AS,
+                                    notify_data_remote_as, 2);
+         return -1;
+       }
+      peer->as = remote_as;
+    }
+  else if ((peer->as_type == AS_SPECIFIED) && (remote_as != peer->as))
     {
       if (bgp_debug_neighbor_events(peer))
        zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
-                  peer->host, remote_as, peer->as);
-      bgp_notify_send_with_data (peer, 
-                                BGP_NOTIFY_OPEN_ERR, 
+                   peer->host, remote_as, peer->as);
+      bgp_notify_send_with_data (peer,
+                                BGP_NOTIFY_OPEN_ERR,
                                 BGP_NOTIFY_OPEN_BAD_PEER_AS,
                                 notify_data_remote_as, 2);
       return -1;
index 4152b8cd2ea60e322555908e44da15c3f247cfe2..abda0684d039d9ee7dbb51b0f34f2771381fb4d6 100644 (file)
@@ -2507,22 +2507,36 @@ peer_remote_as_vty (struct vty *vty, const char *peer_str,
   int ret;
   struct bgp *bgp;
   as_t as;
+  int as_type = AS_SPECIFIED;
   union sockunion su;
 
   bgp = vty->index;
 
-  /* Get AS number.  */
-  VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, BGP_AS4_MAX);
+  if (strncmp(as_str, "internal", strlen("internal")) == 0)
+    {
+      as = 0;
+      as_type = AS_INTERNAL;
+    }
+  else if (strncmp(as_str, "external", strlen("external")) == 0)
+    {
+      as = 0;
+      as_type = AS_EXTERNAL;
+    }
+  else
+    {
+      /* Get AS number.  */
+      VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, BGP_AS4_MAX);
+    }
 
   /* If peer is peer group, call proper function.  */
   ret = str2sockunion (peer_str, &su);
   if (ret < 0)
     {
       /* Check for peer by interface */
-      ret = peer_remote_as (bgp, NULL, peer_str, &as, afi, safi);
+      ret = peer_remote_as (bgp, NULL, peer_str, &as, as_type, afi, safi);
       if (ret < 0)
         {
-          ret = peer_group_remote_as (bgp, peer_str, &as);
+          ret = peer_group_remote_as (bgp, peer_str, &as, as_type);
           if (ret < 0)
             {
               vty_out (vty, "%% Create the peer-group or interface first%s",
@@ -2540,7 +2554,7 @@ peer_remote_as_vty (struct vty *vty, const char *peer_str,
                    VTY_NEWLINE);
           return CMD_WARNING;
         }
-      ret = peer_remote_as (bgp, &su, NULL, &as, afi, safi);
+      ret = peer_remote_as (bgp, &su, NULL, &as, as_type, afi, safi);
     }
 
   /* This peer belongs to peer group.  */
@@ -2558,7 +2572,7 @@ peer_remote_as_vty (struct vty *vty, const char *peer_str,
 
 DEFUN (neighbor_remote_as,
        neighbor_remote_as_cmd,
-       NEIGHBOR_CMD2 "remote-as " CMD_AS_RANGE,
+       NEIGHBOR_CMD2 "remote-as (" CMD_AS_RANGE "|external|internal)",
        NEIGHBOR_STR
        NEIGHBOR_ADDR_STR2
        "Specify a BGP neighbor\n"
@@ -2677,7 +2691,7 @@ DEFUN (no_neighbor,
 
 ALIAS (no_neighbor,
        no_neighbor_remote_as_cmd,
-       NO_NEIGHBOR_CMD "remote-as " CMD_AS_RANGE,
+       NO_NEIGHBOR_CMD "remote-as (" CMD_AS_RANGE "|internal|external)",
        NO_STR
        NEIGHBOR_STR
        NEIGHBOR_ADDR_STR
@@ -2731,7 +2745,7 @@ DEFUN (no_neighbor_peer_group,
 
 DEFUN (no_neighbor_interface_peer_group_remote_as,
        no_neighbor_interface_peer_group_remote_as_cmd,
-       "no neighbor WORD remote-as " CMD_AS_RANGE,
+       "no neighbor WORD remote-as (" CMD_AS_RANGE "|internal|external)",
        NO_STR
        NEIGHBOR_STR
        "Interface name or neighbor tag\n"
@@ -2745,7 +2759,7 @@ DEFUN (no_neighbor_interface_peer_group_remote_as,
   peer = peer_lookup_by_conf_if (vty->index, argv[0]);
   if (peer)
     {
-      peer_as_change (peer, 0);
+      peer_as_change (peer, 0, AS_SPECIFIED);
       return CMD_SUCCESS;
     }
 
@@ -10668,10 +10682,16 @@ bgp_show_one_peer_group (struct vty *vty, struct peer_group *group)
 
   conf = group->conf;
 
+  if (conf->as_type == AS_SPECIFIED ||
+      conf->as_type == AS_EXTERNAL) {
   vty_out (vty, "%sBGP peer-group %s,  remote AS %d%s",
            VTY_NEWLINE, group->name, conf->as, VTY_NEWLINE);
+  } else if (conf->as_type == AS_INTERNAL) {
+    vty_out (vty, "%sBGP peer-group %s,  remote AS %d%s",
+            VTY_NEWLINE, group->name, group->bgp->as, VTY_NEWLINE);
+  }
 
-  if (group->bgp->as == conf->as)
+  if ((group->bgp->as == conf->as) || (conf->as_type == AS_INTERNAL))
     vty_out (vty, "  Peer-group type is internal%s", VTY_NEWLINE);
   else
     vty_out (vty, "  Peer-group type is external%s", VTY_NEWLINE);
index a5794af789be279758e3fa38cc539bbfb0adf1b3..c532e695b105569e8cddd6fa3c957deb5d120f7b 100644 (file)
@@ -830,7 +830,9 @@ peer_calc_sort (struct peer *peer)
   /* Peer-group */
   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
-      if (peer->as)
+      if (peer->as_type != AS_SPECIFIED)
+       return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP : BGP_PEER_EBGP);
+      else if (peer->as)
        return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
       else
        {
@@ -864,6 +866,9 @@ peer_calc_sort (struct peer *peer)
     }
   else
     {
+      if (peer->as_type != AS_SPECIFIED)
+       return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP : BGP_PEER_EBGP);
+
       return (peer->local_as == 0
              ? BGP_PEER_INTERNAL : peer->local_as == peer->as
              ? BGP_PEER_IBGP : BGP_PEER_EBGP);
@@ -1170,7 +1175,7 @@ bgp_peer_conf_if_to_su_update (struct peer *peer)
 /* Create new BGP peer.  */
 struct peer *
 peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp,
-             as_t local_as, as_t remote_as, afi_t afi, safi_t safi)
+             as_t local_as, as_t remote_as, int as_type, afi_t afi, safi_t safi)
 {
   int active;
   struct peer *peer;
@@ -1191,6 +1196,7 @@ peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp,
     }
   peer->local_as = local_as;
   peer->as = remote_as;
+  peer->as_type = as_type;
   peer->local_id = bgp->router_id;
   peer->v_holdtime = bgp->default_holdtime;
   peer->v_keepalive = bgp->default_keepalive;
@@ -1239,9 +1245,9 @@ peer_conf_interface_get(struct bgp *bgp, const char *conf_if, afi_t afi,
     {
       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, 0, 0);
+        peer = peer_create (NULL, conf_if, bgp, bgp->as, AS_SPECIFIED, 0, 0, 0);
       else
-        peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, afi, safi);
+        peer = peer_create (NULL, conf_if, bgp, bgp->as, AS_SPECIFIED, 0, afi, safi);
 
     }
 
@@ -1264,7 +1270,7 @@ peer_create_accept (struct bgp *bgp)
 
 /* Change peer's AS number.  */
 void
-peer_as_change (struct peer *peer, as_t as)
+peer_as_change (struct peer *peer, as_t as, int as_specified)
 {
   bgp_peer_sort_t type;
   struct peer *conf;
@@ -1283,6 +1289,7 @@ peer_as_change (struct peer *peer, as_t as)
     }
   type = peer_sort (peer);
   peer->as = as;
+  peer->as_type = as_specified;
 
   if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
       && ! bgp_confederation_peers_check (peer->bgp, as)
@@ -1340,8 +1347,8 @@ peer_as_change (struct peer *peer, as_t as)
 /* If peer does not exist, create new one.  If peer already exists,
    set AS number to the peer.  */
 int
-peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t *as,
-                           afi_t afi, safi_t safi)
+peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if,
+               as_t *as, int as_type, afi_t afi, safi_t safi)
 {
   struct peer *peer;
   as_t local_as;
@@ -1371,7 +1378,7 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t
            }
          if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
            {
-             if (bgp->as != *as)
+             if ((as_type != AS_INTERNAL) && (bgp->as != *as))
                {
                  *as = peer->as;
                  return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
@@ -1379,7 +1386,7 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t
            }
          else
            {
-             if (bgp->as == *as)
+             if ((as_type != AS_EXTERNAL) && (bgp->as == *as))
                {
                  *as = peer->as;
                  return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
@@ -1389,7 +1396,7 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t
 
       /* Existing peer's AS number change. */
       if (peer->as != *as)
-       peer_as_change (peer, *as);
+       peer_as_change (peer, *as, as_type);
     }
   else
     {
@@ -1410,9 +1417,9 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t
 
       if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
          && afi == AFI_IP && safi == SAFI_UNICAST)
-       peer = peer_create (su, conf_if, bgp, local_as, *as, 0, 0);
+       peer = peer_create (su, conf_if, bgp, local_as, *as, as_type, 0, 0);
       else
-       peer = peer_create (su, conf_if, bgp, local_as, *as, afi, safi);
+       peer = peer_create (su, conf_if, bgp, local_as, *as, as_type, afi, safi);
     }
 
   return 0;
@@ -2065,7 +2072,8 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
 
 /* Peer group's remote AS configuration.  */
 int
-peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
+peer_group_remote_as (struct bgp *bgp, const char *group_name,
+                     as_t *as, int as_type)
 {
   struct peer_group *group;
   struct peer *peer;
@@ -2075,17 +2083,18 @@ peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
   if (! group)
     return -1;
 
-  if (group->conf->as == *as)
+  if ((as_type == group->conf->as_type) && (group->conf->as == *as))
     return 0;
 
+
   /* When we setup peer-group AS number all peer group member's AS
      number must be updated to same number.  */
-  peer_as_change (group->conf, *as);
+  peer_as_change (group->conf, *as, as_type);
 
   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
     {
       if (peer->as != *as)
-       peer_as_change (peer, *as);
+       peer_as_change (peer, *as, as_type);
     }
 
   return 0;
@@ -2145,7 +2154,8 @@ peer_group_remote_as_delete (struct peer_group *group)
   struct peer *peer, *other;
   struct listnode *node, *nnode;
 
-  if (! group->conf->as)
+  if ((group->conf->as_type == AS_UNSPECIFIED) ||
+      ((! group->conf->as) && (group->conf->as_type == AS_SPECIFIED)))
     return 0;
 
   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
@@ -2164,6 +2174,7 @@ peer_group_remote_as_delete (struct peer_group *group)
   list_delete_all_node (group->peer);
 
   group->conf->as = 0;
+  group->conf->as_type = AS_UNSPECIFIED;
 
   return 0;
 }
@@ -2258,10 +2269,11 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer,
   /* Create a new peer. */
   if (! peer)
     {
-      if (! group->conf->as)
+      if ((group->conf->as_type == AS_SPECIFIED) && (! group->conf->as)) {
        return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
+      }
 
-      peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, afi, safi);
+      peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, afi, safi);
       peer->group = group;
       peer->af_group[afi][safi] = 1;
 
@@ -2287,6 +2299,12 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer,
       && strcmp (peer->group->name, group->name) != 0)
     return BGP_ERR_PEER_GROUP_MISMATCH;
 
+  if (peer->as_type == AS_UNSPECIFIED)
+    {
+      peer->as_type = group->conf->as_type;
+      peer->as = group->conf->as;
+    }
+
   if (! group->conf->as)
     {
       if (peer_sort (group->conf) != BGP_PEER_INTERNAL
@@ -2821,7 +2839,7 @@ peer_create_bind_dynamic_neighbor (struct bgp *bgp, union sockunion *su,
   as_t as;
 
   /* Create peer first; we've already checked group config is valid. */
-  peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, 0, 0);
+  peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0);
   if (!peer)
     return NULL;
 
@@ -2916,8 +2934,9 @@ peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su)
   char buf1[SU_ADDRSTRLEN];
 
   prefix = sockunion2hostprefix(su);
-  if (!prefix)
+  if (!prefix) {
     return NULL;
+  }
 
   /* See if incoming connection matches a configured listen range. */
   group = peer_group_lookup_dynamic_neighbor (bgp, prefix, &listen_range);
@@ -2925,6 +2944,7 @@ peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su)
   if (! group)
     return NULL;
 
+
   gbgp = group->bgp;
 
   if (! gbgp)
@@ -5820,15 +5840,28 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
          if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
            vty_out (vty, " neighbor %s peer-group%s", addr,
                     VTY_NEWLINE);
-         if (peer->as)
-           vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
-                    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);
+           }
        }
       else
        {
          if (! g_peer->as)
-           vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
-                    VTY_NEWLINE);
+           {
+             if (g_peer->as_type == AS_SPECIFIED)
+               vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
+                        VTY_NEWLINE);
+           }
          if (peer->af_group[AFI_IP][SAFI_UNICAST])
            vty_out (vty, " neighbor %s peer-group %s%s", addr,
                     peer->group->name, VTY_NEWLINE);
index 0cd72e0e64ce8d30c9595e3ab67a98a5dff184bc..7584faf700be8056d03e216fa666750dc2c213d5 100644 (file)
@@ -29,6 +29,18 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 struct update_subgroup;
 struct bpacket;
 
+/*
+ * Allow the neighbor XXXX remote-as to take internal or external
+ * AS_SPECIFIED is zero to auto-inherit original non-feature/enhancement behavior
+ * in the system.
+ */
+enum {
+  AS_UNSPECIFIED = 0,
+  AS_SPECIFIED,
+  AS_INTERNAL,
+  AS_EXTERNAL,
+};
+
 /* Typedef BGP specific types.  */
 typedef u_int32_t as_t;
 typedef u_int16_t as16_t; /* we may still encounter 16 Bit asnums */
@@ -471,7 +483,8 @@ struct peer
   struct peer_af *peer_af_array[BGP_AF_MAX];
 
   /* Peer's remote AS number. */
-  as_t as;                     
+  int as_type;
+  as_t as;
 
   /* Peer's local AS number. */
   as_t local_as;
@@ -1109,7 +1122,7 @@ extern bgp_peer_sort_t peer_sort (struct peer *peer);
 extern int peer_active (struct peer *);
 extern int peer_active_nego (struct peer *);
 extern struct peer *peer_create(union sockunion *, const char *, struct bgp *,
-                                as_t, as_t, afi_t, safi_t);
+                                as_t, as_t, int, afi_t, safi_t);
 extern struct peer *peer_create_accept (struct bgp *);
 extern void peer_xfer_config (struct peer *dst, struct peer *src);
 extern char *peer_uptime (time_t, char *, size_t);
@@ -1162,10 +1175,10 @@ extern int bgp_listen_limit_unset (struct bgp *);
 extern int bgp_update_delay_active (struct bgp *);
 extern int bgp_update_delay_configured (struct bgp *);
 extern int peer_rsclient_active (struct peer *);
-extern void peer_as_change (struct peer *, as_t);
+extern void peer_as_change (struct peer *, as_t, int);
 extern int peer_remote_as (struct bgp *, union sockunion *,const char *, as_t *,
-                           afi_t, safi_t);
-extern int peer_group_remote_as (struct bgp *, const char *, as_t *);
+                           int, afi_t, safi_t);
+extern int peer_group_remote_as (struct bgp *, const char *, as_t *, int);
 extern int peer_delete (struct peer *peer);
 extern int peer_group_delete (struct peer_group *);
 extern int peer_group_remote_as_delete (struct peer_group *);