]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd-maxmed-administrative-onstartup.patch
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 00:40:42 +0000 (17:40 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 00:40:42 +0000 (17:40 -0700)
COMMAND:

Possible forms of the command configuration:

[no] bgp max-med administrative
[no] bgp max-med administrative <max-med-value>
[no] bgp max-med on-startup <period>
[no] bgp max-med on-startup <period> <max-med-value>

DESCRIPTION:

'administrative' takes effect from the time of the config until the config is
removed.

'on-startup' is effective only at the startup time for the given '<period>'
after the first peer is established.

'<max-med-value>' is used as the MED value to be sent out when the max-med
is effective. Default max-med value is 4294967294.

NOTE:
When max-med is active, MED is changed only in the outgoing attributes to the
peers, it doesn't modify any MED specific state of the attributes in BGP on
the local node.

Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
bgpd/bgp_attr.c
bgpd/bgp_fsm.c
bgpd/bgp_fsm.h
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index 4e38bca20090ac3877a1535d03372a727562164f..e7a6a9e17ef88fbdcadbec4fd21a0b6b1dd5f875 100644 (file)
@@ -2330,12 +2330,13 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
     }
 
   /* MED attribute. */
-  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC) ||
+      bgp->maxmed_active)
     {
       stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
       stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
       stream_putc (s, 4);
-      stream_putl (s, attr->med);
+      stream_putl (s, (bgp->maxmed_active ? bgp->maxmed_value : attr->med));
     }
 
   /* Local preference. */
index efaa1cbc54cd7c7f7e7e3ec023847030af091492..2059a98d12fe5915cd85925be13aaa60d568b8bc 100644 (file)
@@ -686,6 +686,117 @@ bgp_adjust_routeadv (struct peer *peer)
     }
 }
 
+static int
+bgp_maxmed_onstartup_applicable (struct bgp *bgp)
+{
+  if (!bgp->maxmed_onstartup_over)
+    return 1;
+
+  return 0;
+}
+
+int
+bgp_maxmed_onstartup_configured (struct bgp *bgp)
+{
+  if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
+    return 1;
+
+  return 0;
+}
+
+int
+bgp_maxmed_onstartup_active (struct bgp *bgp)
+{
+  if (bgp->t_maxmed_onstartup)
+    return 1;
+
+  return 0;
+}
+
+void
+bgp_maxmed_update (struct bgp *bgp)
+{
+  struct listnode *node, *nnode;
+  struct peer *peer;
+  u_char     maxmed_active;
+  u_int32_t  maxmed_value;
+
+  if (bgp->v_maxmed_admin)
+    {
+      maxmed_active = 1;
+      maxmed_value = bgp->maxmed_admin_value;
+    }
+  else if (bgp->t_maxmed_onstartup)
+    {
+      maxmed_active = 1;
+      maxmed_value = bgp->maxmed_onstartup_value;
+    }
+  else
+    {
+      maxmed_active = 0;
+      maxmed_value = BGP_MAXMED_VALUE_DEFAULT;
+    }
+
+  if (bgp->maxmed_active != maxmed_active ||
+      bgp->maxmed_value != maxmed_value)
+    {
+      bgp->maxmed_active = maxmed_active;
+      bgp->maxmed_value = maxmed_value;
+
+      for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+        bgp_announce_route_all (peer);
+    }
+}
+
+/* The maxmed onstartup timer expiry callback. */
+static int
+bgp_maxmed_onstartup_timer (struct thread *thread)
+{
+  struct bgp *bgp;
+
+  zlog_info ("Max med on startup ended - timer expired.");
+
+  bgp = THREAD_ARG (thread);
+  THREAD_TIMER_OFF (bgp->t_maxmed_onstartup);
+  bgp->maxmed_onstartup_over = 1;
+
+  bgp_maxmed_update(bgp);
+
+  return 0;
+}
+
+static void
+bgp_maxmed_onstartup_begin (struct bgp *bgp)
+{
+  /* Applicable only once in the process lifetime on the startup */
+  if (bgp->maxmed_onstartup_over)
+    return;
+
+  zlog_info ("Begin maxmed onstartup mode - timer %d seconds",
+             bgp->v_maxmed_onstartup);
+
+  THREAD_TIMER_ON (master, bgp->t_maxmed_onstartup,
+                   bgp_maxmed_onstartup_timer,
+                   bgp, bgp->v_maxmed_onstartup);
+
+  if (!bgp->v_maxmed_admin)
+    {
+      bgp->maxmed_active = 1;
+      bgp->maxmed_value = bgp->maxmed_onstartup_value;
+    }
+
+  /* Route announce to all peers should happen after this in bgp_establish() */
+}
+
+static void
+bgp_maxmed_onstartup_process_status_change(struct peer *peer)
+{
+  if (peer->status == Established && !peer->bgp->established)
+    {
+      bgp_maxmed_onstartup_begin(peer->bgp);
+    }
+}
+
 /* The update delay timer expiry callback. */
 static int
 bgp_update_delay_timer (struct thread *thread)
@@ -796,6 +907,16 @@ bgp_fsm_change_status (struct peer *peer, int status)
   if (status == Established)
     UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
 
+  /* If max-med processing is applicable, do the necessary. */
+  if (status == Established)
+    {
+      if (bgp_maxmed_onstartup_configured(peer->bgp) &&
+          bgp_maxmed_onstartup_applicable(peer->bgp))
+        bgp_maxmed_onstartup_process_status_change(peer);
+      else
+        peer->bgp->maxmed_onstartup_over = 1;
+    }
+
   /* If update-delay processing is applicable, do the necessary. */
   if (bgp_update_delay_configured(peer->bgp) &&
       bgp_update_delay_applicable(peer->bgp))
index a4c5a611d0a50fff1476c95aada07df4e9f18885..a1a3ce4d551919b199e0e0962dd0a1c67684055b 100644 (file)
@@ -81,6 +81,9 @@ extern void bgp_timer_set (struct peer *);
 extern void bgp_fsm_change_status (struct peer *peer, int status);
 extern const char *peer_down_str[];
 extern void bgp_update_delay_end (struct bgp *);
+extern void bgp_maxmed_update (struct bgp *);
+extern int bgp_maxmed_onstartup_configured (struct bgp *);
+extern int bgp_maxmed_onstartup_active (struct bgp *);
 
 /**
  * Start the route advertisement timer (that honors MRAI) for all the
index c638484a0c2bfdf01b4fe87b5ccaebcc713e941d..d3b21124a797c3e2136986ffe652211418daaf81 100644 (file)
@@ -705,6 +705,174 @@ bgp_maxpaths_config_vty (struct vty *vty, int peer_type, char *mpaths,
   return CMD_SUCCESS;
 }
 
+DEFUN (bgp_maxmed_admin,
+       bgp_maxmed_admin_cmd,
+       "bgp max-med administrative ",
+       BGP_STR
+       "Advertise routes with max-med\n"
+       "Administratively applied, for an indefinite period\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+
+  bgp->v_maxmed_admin = 1;
+  bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT;
+
+  bgp_maxmed_update(bgp);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (bgp_maxmed_admin_medv,
+       bgp_maxmed_admin_medv_cmd,
+       "bgp max-med administrative <0-4294967294>",
+       BGP_STR
+       "Advertise routes with max-med\n"
+       "Administratively applied, for an indefinite period\n"
+       "Max MED value to be used\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+
+  bgp->v_maxmed_admin = 1;
+  VTY_GET_INTEGER ("max-med admin med-value", bgp->maxmed_admin_value, argv[0]);
+
+  bgp_maxmed_update(bgp);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_maxmed_admin,
+       no_bgp_maxmed_admin_cmd,
+       "no bgp max-med administrative",
+       NO_STR
+       BGP_STR
+       "Advertise routes with max-med\n"
+       "Administratively applied, for an indefinite period\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+
+  bgp->v_maxmed_admin = BGP_MAXMED_ADMIN_UNCONFIGURED;
+  bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT;
+
+  bgp_maxmed_update(bgp);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_maxmed_admin,
+       no_bgp_maxmed_admin_medv_cmd,
+       "no bgp max-med administrative <0-4294967294>",
+       NO_STR
+       BGP_STR
+       "Advertise routes with max-med\n"
+       "Administratively applied, for an indefinite period\n"
+       "Max MED value to be used\n")
+
+
+DEFUN (bgp_maxmed_onstartup,
+       bgp_maxmed_onstartup_cmd,
+       "bgp max-med on-startup <5-86400>",
+       BGP_STR
+       "Advertise routes with max-med\n"
+       "Effective on a startup\n"
+       "Time (seconds) period for max-med\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+
+  if (argc != 1)
+    {
+      vty_out (vty, "%% Must supply max-med on-startup period");
+      return CMD_WARNING;
+    }
+
+  VTY_GET_INTEGER ("max-med on-startup period", bgp->v_maxmed_onstartup, argv[0]);
+  bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT;
+
+  bgp_maxmed_update(bgp);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (bgp_maxmed_onstartup_medv,
+       bgp_maxmed_onstartup_medv_cmd,
+       "bgp max-med on-startup <5-86400> <0-4294967294>",
+       BGP_STR
+       "Advertise routes with max-med\n"
+       "Effective on a startup\n"
+       "Time (seconds) period for max-med\n"
+       "Max MED value to be used\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+
+  if (argc != 2)
+    {
+      vty_out (vty, "%% Must supply max-med on-startup period and med value");
+      return CMD_WARNING;
+    }
+
+  VTY_GET_INTEGER ("max-med on-startup period", bgp->v_maxmed_onstartup, argv[0]);
+  VTY_GET_INTEGER ("max-med on-startup med-value", bgp->maxmed_onstartup_value, argv[1]);
+
+  bgp_maxmed_update(bgp);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_maxmed_onstartup,
+       no_bgp_maxmed_onstartup_cmd,
+       "no bgp max-med on-startup",
+       NO_STR
+       BGP_STR
+       "Advertise routes with max-med\n"
+       "Effective on a startup\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+
+  /* Cancel max-med onstartup if its on */
+  if (bgp->t_maxmed_onstartup)
+    {
+      THREAD_TIMER_OFF (bgp->t_maxmed_onstartup);
+      bgp->maxmed_onstartup_over = 1;
+    }
+
+  bgp->v_maxmed_onstartup = BGP_MAXMED_ONSTARTUP_UNCONFIGURED;
+  bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT;
+
+  bgp_maxmed_update(bgp);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_maxmed_onstartup,
+       no_bgp_maxmed_onstartup_period_cmd,
+       "no bgp max-med on-startup <5-86400>",
+       NO_STR
+       BGP_STR
+       "Advertise routes with max-med\n"
+       "Effective on a startup\n"
+       "Time (seconds) period for max-med\n")
+
+ALIAS (no_bgp_maxmed_onstartup,
+       no_bgp_maxmed_onstartup_period_medv_cmd,
+       "no bgp max-med on-startup <5-86400> <0-4294967294>",
+       NO_STR
+       BGP_STR
+       "Advertise routes with max-med\n"
+       "Effective on a startup\n"
+       "Time (seconds) period for max-med\n"
+       "Max MED value to be used\n")
+
 static int
 bgp_update_delay_config_vty (struct vty *vty, const char *delay,
                              const char *wait)
@@ -7398,6 +7566,11 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi, char *del
                     }
                 }
 
+              if (bgp_maxmed_onstartup_configured(bgp) && bgp->maxmed_active)
+                vty_out (vty, "Max-med on-startup active%s", VTY_NEWLINE);
+              if (bgp->v_maxmed_admin)
+                vty_out (vty, "Max-med administrative active%s", VTY_NEWLINE);
+
               ents = bgp_table_count (bgp->rib[afi][safi]);
               vty_out (vty, "RIB entries %ld, using %s of memory%s", ents,
                        mtype_memstr (memstrbuf, sizeof (memstrbuf),
@@ -9704,6 +9877,17 @@ bgp_vty_init (void)
   install_element (BGP_NODE, &bgp_confederation_peers_cmd);
   install_element (BGP_NODE, &no_bgp_confederation_peers_cmd);
 
+  /* bgp max-med command */
+  install_element (BGP_NODE, &bgp_maxmed_admin_cmd);
+  install_element (BGP_NODE, &no_bgp_maxmed_admin_cmd);
+  install_element (BGP_NODE, &bgp_maxmed_admin_medv_cmd);
+  install_element (BGP_NODE, &no_bgp_maxmed_admin_medv_cmd);
+  install_element (BGP_NODE, &bgp_maxmed_onstartup_cmd);
+  install_element (BGP_NODE, &no_bgp_maxmed_onstartup_cmd);
+  install_element (BGP_NODE, &no_bgp_maxmed_onstartup_period_cmd);
+  install_element (BGP_NODE, &bgp_maxmed_onstartup_medv_cmd);
+  install_element (BGP_NODE, &no_bgp_maxmed_onstartup_period_medv_cmd);
+
   /* bgp update-delay command */
   install_element (BGP_NODE, &bgp_update_delay_cmd);
   install_element (BGP_NODE, &no_bgp_update_delay_cmd);
index 1456beda730ec9710802446657bf84b1c425c34a..347c4bc5f5707b3fbe490b8f7a80b5bb969f05d3 100644 (file)
@@ -5657,6 +5657,21 @@ bgp_config_write (struct vty *vty)
       /* BGP update-delay. */
       bgp_config_write_update_delay (vty, bgp);
 
+      if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
+        {
+          vty_out (vty, " bgp max-med on-startup %d", bgp->v_maxmed_onstartup);
+          if (bgp->maxmed_onstartup_value != BGP_MAXMED_VALUE_DEFAULT)
+            vty_out (vty, " %d", bgp->maxmed_onstartup_value);
+          vty_out (vty, "%s", VTY_NEWLINE);
+        }
+      if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED)
+        {
+          vty_out (vty, " bgp max-med administrative");
+          if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
+            vty_out (vty, " %d", bgp->maxmed_admin_value);
+          vty_out (vty, "%s", VTY_NEWLINE);
+        }
+
       /* write quanta */
       bgp_config_write_wpkt_quanta (vty, bgp);
 
index f1fe586a228c2a9688890d8fbe3980680efe04cb..7cd43cf5a9b7b22f5e9f9718d91552ac00e6c981 100644 (file)
@@ -111,7 +111,21 @@ struct bgp
   as_t *confed_peers;
   int confed_peers_cnt;
 
-  struct thread *t_startup;
+  struct thread *t_startup; /* start-up timer on only once at the beginning */
+
+  u_int32_t v_maxmed_onstartup; /* Duration of max-med on start-up */
+#define BGP_MAXMED_ONSTARTUP_UNCONFIGURED  0 /* 0 means off, its the default */
+  u_int32_t maxmed_onstartup_value; /* Max-med value when active on start-up */
+  struct thread *t_maxmed_onstartup; /* non-null when max-med onstartup is on */
+  u_char    maxmed_onstartup_over; /* Flag to make it effective only once */
+
+  u_char    v_maxmed_admin; /* 1/0 if max-med administrative is on/off */
+#define BGP_MAXMED_ADMIN_UNCONFIGURED  0 /* Off by default */
+  u_int32_t maxmed_admin_value; /* Max-med value when administrative in on */
+#define BGP_MAXMED_VALUE_DEFAULT  4294967294 /* Maximum by default */
+
+  u_char    maxmed_active; /* 1/0 if max-med is active or not */
+  u_int32_t maxmed_value; /* Max-med value when its active */
 
   /* BGP update delay on startup */
   struct thread *t_update_delay;