From: Vipin Kumar <[email protected]>

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 <[email protected]>
Reviewed-by: Daniel Walton <[email protected]>
Signed-off-by: Donald Sharp <[email protected]>
---
 bgpd/bgp_attr.c |   5 +-
 bgpd/bgp_fsm.c  | 121 +++++++++++++++++++++++++++++++++++++
 bgpd/bgp_fsm.h  |   3 +
 bgpd/bgp_vty.c  | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bgpd/bgpd.c     |  15 +++++
 bgpd/bgpd.h     |  16 ++++-
 6 files changed, 341 insertions(+), 3 deletions(-)

diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 8f77f55..6aba287 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -2385,12 +2385,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. */
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 4fbd639..6de4e94 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -678,6 +678,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 (bm->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)
@@ -804,6 +915,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))
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index 16b9b2d..1b90868 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -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
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index c04e8c2..e8e8fc6 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -710,6 +710,174 @@ bgp_maxpaths_config_vty (struct vty *vty, int peer_type, 
const 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)
@@ -7528,6 +7696,11 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int 
afi, int safi)
                     }
                 }
 
+              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),
@@ -9714,6 +9887,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);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index df153fa..2b00ce5 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -5782,6 +5782,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);
 
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index e318e37..adb89c8 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -112,7 +112,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;
-- 
1.9.1


_______________________________________________
Quagga-dev mailing list
[email protected]
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to