summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c5
-rw-r--r--bgpd/bgp_fsm.c121
-rw-r--r--bgpd/bgp_fsm.h3
-rw-r--r--bgpd/bgp_vty.c184
-rw-r--r--bgpd/bgpd.c15
-rw-r--r--bgpd/bgpd.h16
6 files changed, 341 insertions, 3 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 4e38bca20..e7a6a9e17 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -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. */
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index efaa1cbc5..2059a98d1 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -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))
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index a4c5a611d..a1a3ce4d5 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 c638484a0..d3b21124a 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -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);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 1456beda7..347c4bc5f 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -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);
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index f1fe586a2..7cd43cf5a 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -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;