diff options
-rw-r--r-- | bgpd/bgp_attr.c | 5 | ||||
-rw-r--r-- | bgpd/bgp_fsm.c | 121 | ||||
-rw-r--r-- | bgpd/bgp_fsm.h | 3 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 184 | ||||
-rw-r--r-- | bgpd/bgpd.c | 15 | ||||
-rw-r--r-- | bgpd/bgpd.h | 16 |
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; |