]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: 'neighbor x.x.x.x weight' should be per address-family
authorDaniel Walton <dwalton@cumulusnetworks.com>
Mon, 10 Oct 2016 14:53:34 +0000 (07:53 -0700)
committerDaniel Walton <dwalton@cumulusnetworks.com>
Mon, 10 Oct 2016 14:53:34 +0000 (07:53 -0700)
Ticket: CM-13053
Reviewed By: dslice@cumulusnetworks.com

'neighbor x.x.x.x weight' was implemented as a per-peer knob instead of
a per-peer per-afi-safi option. This makes it configurable per-peer
per-afi-safi so that we can do things like soft clear that afi/safi when
weight is modified.

bgpd/bgp_route.c
bgpd/bgp_updgrp.c
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index e53941172b4874ae40893c3dbe845aed2b310d54..764bb6c438d8c521e50f6ceab783994fb4b1c70c 100644 (file)
@@ -1018,8 +1018,8 @@ bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr,
   filter = &peer->filter[afi][safi];
 
   /* Apply default weight value. */
-  if (peer->weight)
-    (bgp_attr_extra_get (attr))->weight = peer->weight;
+  if (peer->weight[afi][safi])
+    (bgp_attr_extra_get (attr))->weight = peer->weight[afi][safi];
 
   if (rmap_name)
     {
@@ -1075,8 +1075,8 @@ bgp_output_modifier (struct peer *peer, struct prefix *p, struct attr *attr,
   filter = &peer->filter[afi][safi];
 
   /* Apply default weight value. */
-  if (peer->weight)
-    (bgp_attr_extra_get (attr))->weight = peer->weight;
+  if (peer->weight[afi][safi])
+    (bgp_attr_extra_get (attr))->weight = peer->weight[afi][safi];
 
   if (rmap_name)
     {
index 29e6243a1a143e88b8cf5da709a4a03be255ffa1..77b979e56e67d02fc45d22ac0c56f545dfbd8f7b 100644 (file)
@@ -140,7 +140,6 @@ conf_copy (struct peer *dst, struct peer *src, afi_t afi, safi_t safi)
   dst->bgp = src->bgp;
   dst->sort = src->sort;
   dst->as = src->as;
-  dst->weight = src->weight;
   dst->v_routeadv = src->v_routeadv;
   dst->flags = src->flags;
   dst->af_flags[afi][safi] = src->af_flags[afi][safi];
index 7c2bcd8bd788df25b9328922abfa556155f47fbe..258a709837e12eeaa089515a205f847288e8567e 100644 (file)
@@ -4881,6 +4881,7 @@ ALIAS (no_neighbor_port,
 /* neighbor weight. */
 static int
 peer_weight_set_vty (struct vty *vty, const char *ip_str, 
+                     afi_t afi, safi_t safi,
                      const char *weight_str)
 {
   int ret;
@@ -4893,12 +4894,13 @@ peer_weight_set_vty (struct vty *vty, const char *ip_str,
 
   VTY_GET_INTEGER_RANGE("weight", weight, weight_str, 0, 65535);
 
-  ret = peer_weight_set (peer, weight);
+  ret = peer_weight_set (peer, afi, safi, weight);
   return bgp_vty_return (vty, ret);
 }
 
 static int
-peer_weight_unset_vty (struct vty *vty, const char *ip_str)
+peer_weight_unset_vty (struct vty *vty, const char *ip_str,
+                       afi_t afi, safi_t safi)
 {
   int ret;
   struct peer *peer;
@@ -4907,7 +4909,7 @@ peer_weight_unset_vty (struct vty *vty, const char *ip_str)
   if (! peer)
     return CMD_WARNING;
 
-  ret = peer_weight_unset (peer);
+  ret = peer_weight_unset (peer, afi, safi);
   return bgp_vty_return (vty, ret);
 }
 
@@ -4919,7 +4921,7 @@ DEFUN (neighbor_weight,
        "Set default weight for routes from this neighbor\n"
        "default weight\n")
 {
-  return peer_weight_set_vty (vty, argv[0], argv[1]);
+  return peer_weight_set_vty (vty, argv[0], bgp_node_afi (vty), bgp_node_safi (vty), argv[1]);
 }
 
 DEFUN (no_neighbor_weight,
@@ -4930,7 +4932,7 @@ DEFUN (no_neighbor_weight,
        NEIGHBOR_ADDR_STR2
        "Set default weight for routes from this neighbor\n")
 {
-  return peer_weight_unset_vty (vty, argv[0]);
+  return peer_weight_unset_vty (vty, argv[0], bgp_node_afi (vty), bgp_node_safi (vty));
 }
 
 ALIAS (no_neighbor_weight,
@@ -12315,11 +12317,6 @@ bgp_show_peer (struct vty *vty, struct peer *p, u_char use_json, json_object *js
           else if (p->update_source)
             json_object_string_add(json_neigh, "updateSource", sockunion2str (p->update_source, buf1, SU_ADDRSTRLEN));
         }
-
-      /* Default weight */
-      if (CHECK_FLAG (p->config, PEER_CONFIG_WEIGHT))
-        json_object_int_add(json_neigh, "defaultWeight", p->weight);
-
     }
   else
     {
@@ -12338,10 +12335,6 @@ bgp_show_peer (struct vty *vty, struct peer *p, u_char use_json, json_object *js
           vty_out (vty, "%s", VTY_NEWLINE);
         }
 
-      /* Default weight */
-      if (CHECK_FLAG (p->config, PEER_CONFIG_WEIGHT))
-        vty_out (vty, "  Default weight %d%s", p->weight, VTY_NEWLINE);
-
       vty_out (vty, "%s", VTY_NEWLINE);
     }
 
@@ -15315,6 +15308,30 @@ bgp_vty_init (void)
   install_element (BGP_NODE, &neighbor_weight_cmd);
   install_element (BGP_NODE, &no_neighbor_weight_cmd);
   install_element (BGP_NODE, &no_neighbor_weight_val_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_weight_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_weight_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_weight_val_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_weight_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_weight_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_weight_val_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_weight_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_weight_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_weight_val_cmd);
+  install_element (BGP_IPV6M_NODE, &neighbor_weight_cmd);
+  install_element (BGP_IPV6M_NODE, &no_neighbor_weight_cmd);
+  install_element (BGP_IPV6M_NODE, &no_neighbor_weight_val_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_weight_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_weight_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_weight_val_cmd);
+  install_element (BGP_VPNV6_NODE, &neighbor_weight_cmd);
+  install_element (BGP_VPNV6_NODE, &no_neighbor_weight_cmd);
+  install_element (BGP_VPNV6_NODE, &no_neighbor_weight_val_cmd);
+  install_element (BGP_ENCAP_NODE, &neighbor_weight_cmd);
+  install_element (BGP_ENCAP_NODE, &no_neighbor_weight_cmd);
+  install_element (BGP_ENCAP_NODE, &no_neighbor_weight_val_cmd);
+  install_element (BGP_ENCAPV6_NODE, &neighbor_weight_cmd);
+  install_element (BGP_ENCAPV6_NODE, &no_neighbor_weight_cmd);
+  install_element (BGP_ENCAPV6_NODE, &no_neighbor_weight_val_cmd);
 
   /* "neighbor override-capability" commands. */
   install_element (BGP_NODE, &neighbor_override_capability_cmd);
index 7d47f18e5410e5f935a098f9d5a2c970006ab1ec..9ad68fbc67168484a4f23dd4a6ba47acdbabb3d5 100644 (file)
@@ -890,7 +890,6 @@ peer_global_config_reset (struct peer *peer)
 
   int v6only;
 
-  peer->weight = 0;
   peer->change_local_as = 0;
   peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? MAXTTL : 1);
   if (peer->update_source)
@@ -1157,7 +1156,6 @@ peer_new (struct bgp *bgp)
   peer->bgp = bgp;
   peer = peer_lock (peer); /* initial reference */
   bgp_lock (bgp);
-  peer->weight = 0;
   peer->password = NULL;
 
   /* Set default flags.  */
@@ -1253,6 +1251,7 @@ peer_xfer_config (struct peer *peer_dst, struct peer *peer_src)
        peer_dst->afc[afi][safi] = peer_src->afc[afi][safi];
        peer_dst->af_flags[afi][safi] = peer_src->af_flags[afi][safi];
        peer_dst->allowas_in[afi][safi] = peer_src->allowas_in[afi][safi];
+       peer_dst->weight[afi][safi] = peer_src->weight[afi][safi];
     }
 
   for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
@@ -2199,9 +2198,6 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer)
   /* GTSM hops */
   peer->gtsm_hops = conf->gtsm_hops;
 
-  /* Weight */
-  peer->weight = conf->weight;
-
   /* this flag is per-neighbor and so has to be preserved */
   v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
 
@@ -2291,6 +2287,9 @@ peer_group2peer_config_copy_af (struct peer_group *group, struct peer *peer,
   /* allowas-in */
   peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
 
+  /* weight */
+  peer->weight[afi][safi] = conf->weight[afi][safi];
+
   /* default-originate route-map */
   if (conf->default_rmap[afi][safi].name)
     {
@@ -3678,6 +3677,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] =
     { PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE,1, peer_change_reset_out },
     { PEER_FLAG_ADDPATH_TX_ALL_PATHS,     1, peer_change_reset },
     { PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset },
+    { PEER_FLAG_WEIGHT,                   0, peer_change_reset_in },
     { 0, 0, 0 }
   };
 
@@ -4513,15 +4513,47 @@ peer_port_unset (struct peer *peer)
   return 0;
 }
 
+/*
+ * Helper function that is called after the name of the policy
+ * being used by a peer has changed (AF specific). Automatically
+ * initiates inbound or outbound processing as needed.
+ */
+static void
+peer_on_policy_change (struct peer *peer, afi_t afi, safi_t safi, int outbound)
+{
+  if (outbound)
+    {
+      update_group_adjust_peer (peer_af_find (peer, afi, safi));
+      if (peer->status == Established)
+        bgp_announce_route(peer, afi, safi);
+    }
+  else
+    {
+      if (peer->status != Established)
+        return;
+
+      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
+        bgp_soft_reconfig_in (peer, afi, safi);
+      else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
+             || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
+        bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
+    }
+}
+
+
 /* neighbor weight. */
 int
-peer_weight_set (struct peer *peer, u_int16_t weight)
+peer_weight_set (struct peer *peer, afi_t afi, safi_t safi, u_int16_t weight)
 {
   struct peer_group *group;
   struct listnode *node, *nnode;
 
-  SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
-  peer->weight = weight;
+  if (peer->weight[afi][safi] != weight)
+    {
+      peer->weight[afi][safi] = weight;
+      SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
+      peer_on_policy_change (peer, afi, safi, 0);
+    }
 
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     return 0;
@@ -4530,35 +4562,71 @@ peer_weight_set (struct peer *peer, u_int16_t weight)
   group = peer->group;
   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
     {
-      peer->weight = group->conf->weight;
+      if (peer->weight[afi][safi] != weight)
+        {
+          peer->weight[afi][safi] = weight;
+          SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
+          peer_on_policy_change (peer, afi, safi, 0);
+        }
     }
-  return 1;
+  return 0;
 }
 
 int
-peer_weight_unset (struct peer *peer)
+peer_weight_unset (struct peer *peer, afi_t afi, safi_t safi)
 {
   struct peer_group *group;
   struct listnode *node, *nnode;
 
-  /* Set default weight. */
-  if (peer_group_active (peer))
-    peer->weight = peer->group->conf->weight;
-  else
-    peer->weight = 0;
-
-  UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
+  /* not the peer-group itself but a peer in a peer-group */
+  if (peer_group_active(peer))
+    {
+      group = peer->group;
 
-  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
-    return 0;
+      /* inherit weight from the peer-group */
+      if (CHECK_FLAG (group->conf->af_flags[afi][safi], PEER_FLAG_WEIGHT))
+        {
+          peer->weight[afi][safi] = group->conf->weight[afi][safi];
+          peer_af_flag_set (peer, afi, safi, PEER_FLAG_WEIGHT);
+          peer_on_policy_change (peer, afi, safi, 0);
+        }
+      else
+        {
+          if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
+            {
+              peer->weight[afi][safi] = 0;
+              peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT);
+              peer_on_policy_change (peer, afi, safi, 0);
+            }
+        }
+    }
 
-  /* peer-group member updates. */
-  group = peer->group;
-  for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+  else
     {
-      peer->weight = 0;
+      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
+        {
+          peer->weight[afi][safi] = 0;
+          peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT);
+          peer_on_policy_change (peer, afi, safi, 0);
+        }
+
+      /* peer-group member updates. */
+      group = peer->group;
+
+      if (group)
+        {
+          for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+            {
+              if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
+                {
+                  peer->weight[afi][safi] = 0;
+                  peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT);
+                  peer_on_policy_change (peer, afi, safi, 0);
+                }
+            }
+        }
     }
-  return 1;
+  return 0;
 }
 
 int
@@ -4788,7 +4856,7 @@ peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
     {
       peer->allowas_in[afi][safi] = allow_num;
       SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
-      peer_change_action (peer, afi, safi, peer_change_reset_in);
+      peer_on_policy_change (peer, afi, safi, 0);
     }
 
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
@@ -4801,7 +4869,7 @@ peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
        {
          peer->allowas_in[afi][safi] = allow_num;
          SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
-         peer_change_action (peer, afi, safi, peer_change_reset_in);
+          peer_on_policy_change (peer, afi, safi, 0);
        }
          
     }
@@ -4818,6 +4886,7 @@ peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
     {
       peer->allowas_in[afi][safi] = 0;
       peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
+      peer_on_policy_change (peer, afi, safi, 0);
     }
 
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
@@ -4830,6 +4899,7 @@ peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
        {
          peer->allowas_in[afi][safi] = 0;
          peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
+          peer_on_policy_change (peer, afi, safi, 0);
        }
     }
   return 0;
@@ -5064,33 +5134,6 @@ peer_password_unset (struct peer *peer)
   return 0;
 }
 
-/*
- * Helper function that is called after the name of the policy
- * being used by a peer has changed (AF specific). Automatically
- * initiates inbound or outbound processing as needed.
- */
-static void
-peer_on_policy_change (struct peer *peer, afi_t afi, safi_t safi, int outbound)
-{
-  if (outbound)
-    {
-      update_group_adjust_peer (peer_af_find (peer, afi, safi));
-      if (peer->status == Established)
-        bgp_announce_route(peer, afi, safi);
-    }
-  else
-    {
-      if (peer->status != Established)
-        return;
-
-      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
-        bgp_soft_reconfig_in (peer, afi, safi);
-      else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
-             || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
-        bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
-    }
-}
-
 
 /* Set distribute list to the peer. */
 int
@@ -6623,16 +6666,6 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
                peer->connect, VTY_NEWLINE);
     }
 
-  /* weight */
-  if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
-    {
-      if (! peer_group_active (peer) || g_peer->weight != peer->weight)
-        {
-          vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
-                   VTY_NEWLINE);
-        }
-    }
-
   /* capability dynamic */
   if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
     {
@@ -6995,6 +7028,20 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
           }
       }
 
+  /* weight */
+  if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_WEIGHT))
+    if (! peer_group_active (peer)
+       || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_WEIGHT)
+       || peer->weight[afi][safi] != g_peer->weight[afi][safi])
+      {
+       if (peer->weight[afi][safi])
+          {
+            afi_header_vty_out (vty, afi, safi, write,
+                                "  neighbor %s weight %d%s",
+                                addr, peer->weight[afi][safi], VTY_NEWLINE);
+          }
+      }
+
   /* Filter. */
   bgp_config_write_filter (vty, peer, afi, safi, write);
 
index cc55fb87d1c350281adf63644905e95ed6b4b7c0..ee105201e88d46652e677a187883b650fbf25098 100644 (file)
@@ -697,6 +697,7 @@ struct peer
 #define PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE (1 << 21) /* remove-private-as all replace-as */
 #define PEER_FLAG_ADDPATH_TX_ALL_PATHS      (1 << 22) /* addpath-tx-all-paths */
 #define PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS (1 << 23) /* addpath-tx-bestpath-per-AS */
+#define PEER_FLAG_WEIGHT                    (1 << 24) /* weight */
 
   /* MD5 password */
   char *password;
@@ -729,12 +730,10 @@ struct peer
 
   /* Default attribute value for the peer. */
   u_int32_t config;
-#define PEER_CONFIG_WEIGHT            (1 << 0) /* Default weight. */
-#define PEER_CONFIG_TIMER             (1 << 1) /* keepalive & holdtime */
-#define PEER_CONFIG_CONNECT           (1 << 2) /* connect */
-#define PEER_CONFIG_ROUTEADV          (1 << 3) /* route advertise */
+#define PEER_CONFIG_TIMER             (1 << 0) /* keepalive & holdtime */
+#define PEER_CONFIG_CONNECT           (1 << 1) /* connect */
+#define PEER_CONFIG_ROUTEADV          (1 << 2) /* route advertise */
 
-  u_int32_t weight;
   u_int32_t holdtime;
   u_int32_t keepalive;
   u_int32_t connect;
@@ -828,6 +827,9 @@ struct peer
   /* allowas-in. */
   char allowas_in[AFI_MAX][SAFI_MAX];
 
+  /* weight */
+  unsigned long weight[AFI_MAX][SAFI_MAX];
+
   /* peer reset cause */
   char last_reset;
 #define PEER_DOWN_RID_CHANGE             1 /* bgp router-id command */
@@ -1292,8 +1294,8 @@ extern int peer_default_originate_unset (struct peer *, afi_t, safi_t);
 extern int peer_port_set (struct peer *, u_int16_t);
 extern int peer_port_unset (struct peer *);
 
-extern int peer_weight_set (struct peer *, u_int16_t);
-extern int peer_weight_unset (struct peer *);
+extern int peer_weight_set (struct peer *, afi_t, safi_t, u_int16_t);
+extern int peer_weight_unset (struct peer *, afi_t, safi_t);
 
 extern int peer_timers_set (struct peer *, u_int32_t keepalive, u_int32_t holdtime);
 extern int peer_timers_unset (struct peer *);