/* Compare two bgp route entity. br is preferable then return 1. */
static int
bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
- int *paths_eq)
+ int *paths_eq, struct bgp_maxpaths_cfg *mpath_cfg)
{
struct attr *newattr, *existattr;
struct attr_extra *newattre, *existattre;
if (newm > existm)
ret = 0;
+ /* 8.1. Same IGP metric. Compare the cluster list length as
+ representative of IGP hops metric. Rewrite the metric value
+ pair (newm, existm) with the cluster list length. Prefer the
+ path with smaller cluster list length. */
+ if (newm == existm)
+ {
+ if (peer_sort (new->peer) == BGP_PEER_IBGP
+ && peer_sort (exist->peer) == BGP_PEER_IBGP
+ && CHECK_FLAG (mpath_cfg->ibgp_flags,
+ BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))
+ {
+ newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
+ existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
+ if (newm < existm)
+ ret = 1;
+ if (newm > existm)
+ ret = 0;
+ }
+ }
+
/* 9. Maximum path check. */
if (newm == existm)
{
return 0;
/* 12. Cluster length comparision. */
- new_cluster = exist_cluster = 0;
-
- if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
- new_cluster = newattre->cluster->length;
- if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
- exist_cluster = existattre->cluster->length;
+ new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
+ exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
if (new_cluster < exist_cluster)
return 1;
{
if (CHECK_FLAG (ri2->flags, BGP_INFO_SELECTED))
old_select = ri2;
- if (bgp_info_cmp (bgp, ri2, new_select, &paths_eq))
+ if (bgp_info_cmp (bgp, ri2, new_select, &paths_eq,
+ mpath_cfg))
{
bgp_info_unset_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
new_select = ri2;
bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_SELECTED);
- if (bgp_info_cmp (bgp, ri, new_select, &paths_eq))
+ if (bgp_info_cmp (bgp, ri, new_select, &paths_eq, mpath_cfg))
{
if (do_mpath && bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
bgp_mp_dmed_deselect (new_select);
return CMD_SUCCESS;
}
-/* Maximum-paths configuration */
-DEFUN (bgp_maxpaths,
- bgp_maxpaths_cmd,
- "maximum-paths <1-255>",
- "Forward packets over multiple paths\n"
- "Number of paths\n")
+/**
+ * Central routine for maximum-paths configuration.
+ * @peer_type: BGP_PEER_EBGP or BGP_PEER_IBGP
+ * @set: 1 for setting values, 0 for removing the max-paths config.
+ */
+int
+bgp_maxpaths_config_vty (struct vty *vty, int peer_type, char *mpaths,
+ u_int16_t options, int set)
{
struct bgp *bgp;
u_int16_t maxpaths;
int ret;
+ afi_t afi;
+ safi_t safi;
bgp = vty->index;
+ afi = bgp_node_afi (vty);
+ safi = bgp_node_safi (vty);
- VTY_GET_INTEGER_RANGE ("maximum-paths", maxpaths, argv[0], 1, 255);
+ if (set)
+ {
+ VTY_GET_INTEGER_RANGE ("maximum-paths", maxpaths, mpaths, 1, 255);
+ ret = bgp_maximum_paths_set (bgp, afi, safi, peer_type, maxpaths,
+ options);
+ }
+ else
+ ret = bgp_maximum_paths_unset (bgp, afi, safi, peer_type);
- ret = bgp_maximum_paths_set (bgp, bgp_node_afi (vty), bgp_node_safi(vty),
- BGP_PEER_EBGP, maxpaths);
if (ret < 0)
{
vty_out (vty,
- "%% Failed to set maximum-paths %u for afi %u, safi %u%s",
- maxpaths, bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE);
+ "%% Failed to %sset maximum-paths %s %u for afi %u, safi %u%s",
+ (set == 1) ? "" : "un",
+ (peer_type == BGP_PEER_EBGP) ? "ebgp" : "ibgp",
+ maxpaths, afi, safi, VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
+
+/* Maximum-paths configuration */
+DEFUN (bgp_maxpaths,
+ bgp_maxpaths_cmd,
+ "maximum-paths <1-255>",
+ "Forward packets over multiple paths\n"
+ "Number of paths\n")
+{
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP, argv[0], 0, 1);
+}
+
DEFUN (bgp_maxpaths_ibgp,
bgp_maxpaths_ibgp_cmd,
"maximum-paths ibgp <1-255>",
"iBGP-multipath\n"
"Number of paths\n")
{
- struct bgp *bgp;
- u_int16_t maxpaths;
- int ret;
-
- bgp = vty->index;
-
- VTY_GET_INTEGER_RANGE ("maximum-paths", maxpaths, argv[0], 1, 255);
-
- ret = bgp_maximum_paths_set (bgp, bgp_node_afi (vty), bgp_node_safi(vty),
- BGP_PEER_IBGP, maxpaths);
- if (ret < 0)
- {
- vty_out (vty,
- "%% Failed to set maximum-paths ibgp %u for afi %u, safi %u%s",
- maxpaths, bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE);
- return CMD_WARNING;
- }
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, argv[0], 0, 1);
+}
- return CMD_SUCCESS;
+DEFUN (bgp_maxpaths_ibgp_cluster,
+ bgp_maxpaths_ibgp_cluster_cmd,
+ "maximum-paths ibgp <1-255> equal-cluster-length",
+ "Forward packets over multiple paths\n"
+ "iBGP-multipath\n"
+ "Number of paths\n"
+ "Match the cluster length\n")
+{
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, argv[0],
+ BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN, 1);
}
DEFUN (no_bgp_maxpaths,
"Forward packets over multiple paths\n"
"Number of paths\n")
{
- struct bgp *bgp;
- int ret;
-
- bgp = vty->index;
-
- ret = bgp_maximum_paths_unset (bgp, bgp_node_afi (vty), bgp_node_safi(vty),
- BGP_PEER_EBGP);
- if (ret < 0)
- {
- vty_out (vty,
- "%% Failed to unset maximum-paths for afi %u, safi %u%s",
- bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- return CMD_SUCCESS;
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP, NULL, 0, 0);
}
ALIAS (no_bgp_maxpaths,
"iBGP-multipath\n"
"Number of paths\n")
{
- struct bgp *bgp;
- int ret;
-
- bgp = vty->index;
-
- ret = bgp_maximum_paths_unset (bgp, bgp_node_afi (vty), bgp_node_safi(vty),
- BGP_PEER_IBGP);
- if (ret < 0)
- {
- vty_out (vty,
- "%% Failed to unset maximum-paths ibgp for afi %u, safi %u%s",
- bgp_node_afi (vty), bgp_node_safi(vty), VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- return CMD_SUCCESS;
+ return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, NULL, 0, 0);
}
ALIAS (no_bgp_maxpaths_ibgp,
"iBGP-multipath\n"
"Number of paths\n")
+ALIAS (no_bgp_maxpaths_ibgp,
+ no_bgp_maxpaths_ibgp_cluster_cmd,
+ "no maximum-paths ibgp <1-255> equal-cluster-length",
+ NO_STR
+ "Forward packets over multiple paths\n"
+ "iBGP-multipath\n"
+ "Number of paths\n"
+ "Match the cluster length\n")
+
int
bgp_config_write_maxpaths (struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi, int *write)
if (bgp->maxpaths[afi][safi].maxpaths_ibgp != BGP_DEFAULT_MAXPATHS)
{
bgp_config_write_family_header (vty, afi, safi, write);
- vty_out (vty, " maximum-paths ibgp %d%s",
- bgp->maxpaths[afi][safi].maxpaths_ibgp, VTY_NEWLINE);
+ vty_out (vty, " maximum-paths ibgp %d",
+ bgp->maxpaths[afi][safi].maxpaths_ibgp);
+ if (CHECK_FLAG (bgp->maxpaths[afi][safi].ibgp_flags,
+ BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))
+ vty_out (vty, " equal-cluster-length");
+ vty_out (vty, "%s", VTY_NEWLINE);
}
return 0;
install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_cmd);
install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_arg_cmd);
install_element (BGP_NODE, &bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_cmd);
install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_arg_cmd);
+ install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_cluster_cmd);
install_element (BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_cmd);
+ install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_cluster_cmd);
install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_arg_cmd);
install_element (BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cmd);
install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_arg_cmd);
+ install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cluster_cmd);
/* "timers bgp" commands. */
install_element (BGP_NODE, &bgp_timers_cmd);