From: Donald Sharp Date: Wed, 20 May 2015 00:40:42 +0000 (-0700) Subject: bgpd-maxmed-administrative-onstartup.patch X-Git-Tag: frr-2.0-rc1~1528 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=abc920f85ea2e2e42c6cf1df7c14373ec1226d20;p=mirror%2Ffrr.git bgpd-maxmed-administrative-onstartup.patch COMMAND: Possible forms of the command configuration: [no] bgp max-med administrative [no] bgp max-med administrative [no] bgp max-med on-startup [no] bgp max-med on-startup 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 '' after the first peer is established. '' 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 Reviewed-by: Daniel Walton --- diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 4e38bca200..e7a6a9e17e 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 efaa1cbc54..2059a98d12 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 a4c5a611d0..a1a3ce4d55 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 c638484a0c..d3b21124a7 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 1456beda73..347c4bc5f5 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 f1fe586a22..7cd43cf5a9 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;