aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/sr/sr_steering.c
diff options
context:
space:
mode:
authorPablo Camarillo <pcamaril@cisco.com>2017-04-24 17:51:56 +0200
committerNeale Ranns <nranns@cisco.com>2017-05-05 11:38:39 +0000
commit5d73eecd63018db69b10bf56adeec9cc5cf92790 (patch)
tree5fc242e79737b2a95a75d44bfbde3d4d91db4c9f /src/vnet/sr/sr_steering.c
parenta774b53623f60b5e8ea8ed634d6a41e847743715 (diff)
First commit SR MPLS
Change-Id: I961685a2a0e4c314049444c64eb6ccf877c278dd Signed-off-by: Pablo Camarillo <pcamaril@cisco.com>
Diffstat (limited to 'src/vnet/sr/sr_steering.c')
-rwxr-xr-xsrc/vnet/sr/sr_steering.c573
1 files changed, 0 insertions, 573 deletions
diff --git a/src/vnet/sr/sr_steering.c b/src/vnet/sr/sr_steering.c
deleted file mode 100755
index 04646198de1..00000000000
--- a/src/vnet/sr/sr_steering.c
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
- * sr_steering.c: ipv6 segment routing steering into SR policy
- *
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file
- * @brief Packet steering into SR Policies
- *
- * This file is in charge of handling the FIB appropiatly to steer packets
- * through SR Policies as defined in 'sr_policy_rewrite.c'. Notice that here
- * we are only doing steering. SR policy application is done in
- * sr_policy_rewrite.c
- *
- * Supports:
- * - Steering of IPv6 traffic Destination Address based
- * - Steering of IPv4 traffic Destination Address based
- * - Steering of L2 frames, interface based (sw interface)
- */
-
-#include <vlib/vlib.h>
-#include <vnet/vnet.h>
-#include <vnet/sr/sr.h>
-#include <vnet/ip/ip.h>
-#include <vnet/sr/sr_packet.h>
-#include <vnet/ip/ip6_packet.h>
-#include <vnet/fib/ip6_fib.h>
-#include <vnet/dpo/dpo.h>
-
-#include <vppinfra/error.h>
-#include <vppinfra/elog.h>
-
-/**
- * @brief Steer traffic L2 and L3 traffic through a given SR policy
- *
- * @param is_del
- * @param bsid is the bindingSID of the SR Policy (alt to sr_policy_index)
- * @param sr_policy is the index of the SR Policy (alt to bsid)
- * @param table_id is the VRF where to install the FIB entry for the BSID
- * @param prefix is the IPv4/v6 address for L3 traffic type
- * @param mask_width is the mask for L3 traffic type
- * @param sw_if_index is the incoming interface for L2 traffic
- * @param traffic_type describes the type of traffic
- *
- * @return 0 if correct, else error
- */
-int
-sr_steering_policy (int is_del, ip6_address_t * bsid, u32 sr_policy_index,
- u32 table_id, ip46_address_t * prefix, u32 mask_width,
- u32 sw_if_index, u8 traffic_type)
-{
- ip6_sr_main_t *sm = &sr_main;
- sr_steering_key_t key;
- ip6_sr_steering_policy_t *steer_pl;
- fib_prefix_t pfx = { 0 };
-
- ip6_sr_policy_t *sr_policy = 0;
- uword *p = 0;
-
- memset (&key, 0, sizeof (sr_steering_key_t));
-
- /* Compute the steer policy key */
- if (traffic_type == SR_STEER_IPV4 || traffic_type == SR_STEER_IPV6)
- {
- key.l3.prefix.as_u64[0] = prefix->as_u64[0];
- key.l3.prefix.as_u64[1] = prefix->as_u64[1];
- key.l3.mask_width = mask_width;
- key.l3.fib_table = (table_id != (u32) ~ 0 ? table_id : 0);
- }
- else if (traffic_type == SR_STEER_L2)
- {
- key.l2.sw_if_index = sw_if_index;
-
- /* Sanitise the SW_IF_INDEX */
- if (pool_is_free_index (sm->vnet_main->interface_main.sw_interfaces,
- sw_if_index))
- return -3;
-
- vnet_sw_interface_t *sw =
- vnet_get_sw_interface (sm->vnet_main, sw_if_index);
- if (sw->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
- return -3;
- }
- else
- return -1;
-
- key.traffic_type = traffic_type;
-
- /* Search for the item */
- p = mhash_get (&sm->sr_steer_policies_hash, &key);
-
- if (p)
- {
- /* Retrieve Steer Policy function */
- steer_pl = pool_elt_at_index (sm->steer_policies, p[0]);
-
- if (is_del)
- {
- if (steer_pl->classify.traffic_type == SR_STEER_IPV6)
- {
- /* Remove FIB entry */
- pfx.fp_proto = FIB_PROTOCOL_IP6;
- pfx.fp_len = steer_pl->classify.l3.mask_width;
- pfx.fp_addr.ip6 = steer_pl->classify.l3.prefix.ip6;
-
- fib_table_entry_delete (fib_table_find
- (FIB_PROTOCOL_IP6,
- steer_pl->classify.l3.fib_table),
- &pfx, FIB_SOURCE_SR);
- }
- else if (steer_pl->classify.traffic_type == SR_STEER_IPV4)
- {
- /* Remove FIB entry */
- pfx.fp_proto = FIB_PROTOCOL_IP4;
- pfx.fp_len = steer_pl->classify.l3.mask_width;
- pfx.fp_addr.ip4 = steer_pl->classify.l3.prefix.ip4;
-
- fib_table_entry_delete (fib_table_find
- (FIB_PROTOCOL_IP4,
- steer_pl->classify.l3.fib_table), &pfx,
- FIB_SOURCE_SR);
- }
- else if (steer_pl->classify.traffic_type == SR_STEER_L2)
- {
- /* Remove HW redirection */
- vnet_feature_enable_disable ("device-input",
- "sr-policy-rewrite-encaps-l2",
- sw_if_index, 0, 0, 0);
- sm->sw_iface_sr_policies[sw_if_index] = ~(u32) 0;
-
- /* Remove promiscous mode from interface */
- vnet_main_t *vnm = vnet_get_main ();
- ethernet_main_t *em = &ethernet_main;
- ethernet_interface_t *eif =
- ethernet_get_interface (em, sw_if_index);
-
- if (!eif)
- goto cleanup_error_redirection;
-
- ethernet_set_flags (vnm, sw_if_index, 0);
- }
-
- /* Delete SR steering policy entry */
- pool_put (sm->steer_policies, steer_pl);
- mhash_unset (&sm->sr_steer_policies_hash, &key, NULL);
-
- /* If no more SR policies or steering policies */
- if (!pool_elts (sm->sr_policies) && !pool_elts (sm->steer_policies))
- {
- fib_table_unlock (sm->fib_table_ip6, FIB_PROTOCOL_IP6);
- fib_table_unlock (sm->fib_table_ip4, FIB_PROTOCOL_IP6);
- sm->fib_table_ip6 = (u32) ~ 0;
- sm->fib_table_ip4 = (u32) ~ 0;
- }
-
- return 1;
- }
- else /* It means user requested to update an existing SR steering policy */
- {
- /* Retrieve SR steering policy */
- if (bsid)
- {
- p = mhash_get (&sm->sr_policies_index_hash, bsid);
- if (p)
- sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
- else
- return -2;
- }
- else
- sr_policy = pool_elt_at_index (sm->sr_policies, sr_policy_index);
-
- if (!sr_policy)
- return -2;
-
- steer_pl->sr_policy = sr_policy - sm->sr_policies;
-
- /* Remove old FIB/hw redirection and create a new one */
- if (steer_pl->classify.traffic_type == SR_STEER_IPV6)
- {
- /* Remove FIB entry */
- pfx.fp_proto = FIB_PROTOCOL_IP6;
- pfx.fp_len = steer_pl->classify.l3.mask_width;
- pfx.fp_addr.ip6 = steer_pl->classify.l3.prefix.ip6;
-
- fib_table_entry_delete (fib_table_find
- (FIB_PROTOCOL_IP6,
- steer_pl->classify.l3.fib_table),
- &pfx, FIB_SOURCE_SR);
-
- /* Create a new one */
- goto update_fib;
- }
- else if (steer_pl->classify.traffic_type == SR_STEER_IPV4)
- {
- /* Remove FIB entry */
- pfx.fp_proto = FIB_PROTOCOL_IP4;
- pfx.fp_len = steer_pl->classify.l3.mask_width;
- pfx.fp_addr.ip4 = steer_pl->classify.l3.prefix.ip4;
-
- fib_table_entry_delete (fib_table_find
- (FIB_PROTOCOL_IP4,
- steer_pl->classify.l3.fib_table),
- &pfx, FIB_SOURCE_SR);
-
- /* Create a new one */
- goto update_fib;
- }
- else if (steer_pl->classify.traffic_type == SR_STEER_L2)
- {
- /* Update L2-HW redirection */
- goto update_fib;
- }
- }
- }
- else
- /* delete; steering policy does not exist; complain */
- if (is_del)
- return -4;
-
- /* Retrieve SR policy */
- if (bsid)
- {
- p = mhash_get (&sm->sr_policies_index_hash, bsid);
- if (p)
- sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
- else
- return -2;
- }
- else
- sr_policy = pool_elt_at_index (sm->sr_policies, sr_policy_index);
-
- /* Create a new steering policy */
- pool_get (sm->steer_policies, steer_pl);
- memset (steer_pl, 0, sizeof (*steer_pl));
-
- if (traffic_type == SR_STEER_IPV4 || traffic_type == SR_STEER_IPV6)
- {
- clib_memcpy (&steer_pl->classify.l3.prefix, prefix,
- sizeof (ip46_address_t));
- steer_pl->classify.l3.mask_width = mask_width;
- steer_pl->classify.l3.fib_table =
- (table_id != (u32) ~ 0 ? table_id : 0);
- steer_pl->classify.traffic_type = traffic_type;
- }
- else if (traffic_type == SR_STEER_L2)
- {
- steer_pl->classify.l2.sw_if_index = sw_if_index;
- steer_pl->classify.traffic_type = traffic_type;
- }
- else
- {
- /* Incorrect API usage. Should never get here */
- pool_put (sm->steer_policies, steer_pl);
- mhash_unset (&sm->sr_steer_policies_hash, &key, NULL);
- return -1;
- }
- steer_pl->sr_policy = sr_policy - sm->sr_policies;
-
- /* Create and store key */
- mhash_set (&sm->sr_steer_policies_hash, &key, steer_pl - sm->steer_policies,
- NULL);
-
- if (traffic_type == SR_STEER_L2)
- {
- if (!sr_policy->is_encap)
- goto cleanup_error_encap;
-
- if (vnet_feature_enable_disable
- ("device-input", "sr-pl-rewrite-encaps-l2", sw_if_index, 1, 0, 0))
- goto cleanup_error_redirection;
-
- /* Set promiscous mode on interface */
- vnet_main_t *vnm = vnet_get_main ();
- ethernet_main_t *em = &ethernet_main;
- ethernet_interface_t *eif = ethernet_get_interface (em, sw_if_index);
-
- if (!eif)
- goto cleanup_error_redirection;
-
- ethernet_set_flags (vnm, sw_if_index,
- ETHERNET_INTERFACE_FLAG_ACCEPT_ALL);
- }
- else if (traffic_type == SR_STEER_IPV4)
- if (!sr_policy->is_encap)
- goto cleanup_error_encap;
-
-update_fib:
- /* FIB API calls - Recursive route through the BindingSID */
- if (traffic_type == SR_STEER_IPV6)
- {
- pfx.fp_proto = FIB_PROTOCOL_IP6;
- pfx.fp_len = steer_pl->classify.l3.mask_width;
- pfx.fp_addr.ip6 = steer_pl->classify.l3.prefix.ip6;
-
- fib_table_entry_path_add (fib_table_find (FIB_PROTOCOL_IP6,
- (table_id !=
- (u32) ~ 0 ?
- table_id : 0)),
- &pfx, FIB_SOURCE_SR,
- FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT,
- FIB_PROTOCOL_IP6,
- (ip46_address_t *) & sr_policy->bsid, ~0,
- sm->fib_table_ip6, 1, NULL,
- FIB_ROUTE_PATH_FLAG_NONE);
- }
- else if (traffic_type == SR_STEER_IPV4)
- {
- pfx.fp_proto = FIB_PROTOCOL_IP4;
- pfx.fp_len = steer_pl->classify.l3.mask_width;
- pfx.fp_addr.ip4 = steer_pl->classify.l3.prefix.ip4;
-
- fib_table_entry_path_add (fib_table_find (FIB_PROTOCOL_IP4,
- (table_id !=
- (u32) ~ 0 ?
- table_id : 0)),
- &pfx, FIB_SOURCE_SR,
- FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT,
- FIB_PROTOCOL_IP6,
- (ip46_address_t *) & sr_policy->bsid, ~0,
- sm->fib_table_ip4, 1, NULL,
- FIB_ROUTE_PATH_FLAG_NONE);
- }
- else if (traffic_type == SR_STEER_L2)
- {
- if (sw_if_index < vec_len (sm->sw_iface_sr_policies))
- sm->sw_iface_sr_policies[sw_if_index] = steer_pl->sr_policy;
- else
- {
- vec_resize (sm->sw_iface_sr_policies,
- (pool_len (sm->vnet_main->interface_main.sw_interfaces)
- - vec_len (sm->sw_iface_sr_policies)));
- sm->sw_iface_sr_policies[sw_if_index] = steer_pl->sr_policy;
- }
- }
-
- return 0;
-
-cleanup_error_encap:
- pool_put (sm->steer_policies, steer_pl);
- mhash_unset (&sm->sr_steer_policies_hash, &key, NULL);
- return -5;
-
-cleanup_error_redirection:
- pool_put (sm->steer_policies, steer_pl);
- mhash_unset (&sm->sr_steer_policies_hash, &key, NULL);
- return -3;
-}
-
-static clib_error_t *
-sr_steer_policy_command_fn (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- vnet_main_t *vnm = vnet_get_main ();
-
- int is_del = 0;
-
- ip46_address_t prefix;
- u32 dst_mask_width = 0;
- u32 sw_if_index = (u32) ~ 0;
- u8 traffic_type = 0;
- u32 fib_table = (u32) ~ 0;
-
- ip6_address_t bsid;
- u32 sr_policy_index = (u32) ~ 0;
-
- u8 sr_policy_set = 0;
-
- memset (&prefix, 0, sizeof (ip46_address_t));
-
- int rv;
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "del"))
- is_del = 1;
- else if (!traffic_type
- && unformat (input, "l3 %U/%d", unformat_ip6_address,
- &prefix.ip6, &dst_mask_width))
- traffic_type = SR_STEER_IPV6;
- else if (!traffic_type
- && unformat (input, "l3 %U/%d", unformat_ip4_address,
- &prefix.ip4, &dst_mask_width))
- traffic_type = SR_STEER_IPV4;
- else if (!traffic_type
- && unformat (input, "l2 %U", unformat_vnet_sw_interface, vnm,
- &sw_if_index))
- traffic_type = SR_STEER_L2;
- else if (!sr_policy_set
- && unformat (input, "via sr policy index %d",
- &sr_policy_index))
- sr_policy_set = 1;
- else if (!sr_policy_set
- && unformat (input, "via sr policy bsid %U",
- unformat_ip6_address, &bsid))
- sr_policy_set = 1;
- else if (fib_table == (u32) ~ 0
- && unformat (input, "fib-table %d", &fib_table));
- else
- break;
- }
-
- if (!traffic_type)
- return clib_error_return (0, "No L2/L3 traffic specified");
- if (!sr_policy_set)
- return clib_error_return (0, "No SR policy specified");
-
- /* Make sure that the prefixes are clean */
- if (traffic_type == SR_STEER_IPV4)
- {
- u32 mask =
- (dst_mask_width ? (0xFFFFFFFFu >> (32 - dst_mask_width)) : 0);
- prefix.ip4.as_u32 &= mask;
- }
- else if (traffic_type == SR_STEER_IPV6)
- {
- ip6_address_t mask;
- ip6_address_mask_from_width (&mask, dst_mask_width);
- ip6_address_mask (&prefix.ip6, &mask);
- }
-
- rv =
- sr_steering_policy (is_del, (sr_policy_index == ~(u32) 0 ? &bsid : NULL),
- sr_policy_index, fib_table, &prefix, dst_mask_width,
- sw_if_index, traffic_type);
-
- switch (rv)
- {
- case 0:
- break;
- case 1:
- return 0;
- case -1:
- return clib_error_return (0, "Incorrect API usage.");
- case -2:
- return clib_error_return (0,
- "The requested SR policy could not be located. Review the BSID/index.");
- case -3:
- return clib_error_return (0,
- "Unable to do SW redirect. Incorrect interface.");
- case -4:
- return clib_error_return (0,
- "The requested SR steering policy could not be deleted.");
- case -5:
- return clib_error_return (0,
- "The SR policy is not an encapsulation one.");
- default:
- return clib_error_return (0, "BUG: sr steer policy returns %d", rv);
- }
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (sr_steer_policy_command, static) = {
- .path = "sr steer",
- .short_help = "sr steer (del) [l3 <ip_addr/mask>|l2 <sf_if>]"
- "via sr policy [index <sr_policy_index>|bsid <bsid_ip6_addr>]"
- "(fib-table <fib_table_index>)",
- .long_help =
- "\tSteer a L2 or L3 traffic through an existing SR policy.\n"
- "\tExamples:\n"
- "\t\tsr steer l3 2001::/64 via sr_policy index 5\n"
- "\t\tsr steer l3 2001::/64 via sr_policy bsid 2010::9999:1\n"
- "\t\tsr steer l2 GigabitEthernet0/5/0 via sr_policy index 5\n"
- "\t\tsr steer del l3 2001::/64 via sr_policy index 5\n",
- .function = sr_steer_policy_command_fn,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-show_sr_steering_policies_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- ip6_sr_main_t *sm = &sr_main;
- ip6_sr_steering_policy_t **steer_policies = 0;
- ip6_sr_steering_policy_t *steer_pl;
-
- vnet_main_t *vnm = vnet_get_main ();
-
- ip6_sr_policy_t *pl = 0;
- int i;
-
- vlib_cli_output (vm, "SR steering policies:");
- /* *INDENT-OFF* */
- pool_foreach (steer_pl, sm->steer_policies, ({vec_add1(steer_policies, steer_pl);}));
- /* *INDENT-ON* */
- vlib_cli_output (vm, "Traffic\t\tSR policy BSID");
- for (i = 0; i < vec_len (steer_policies); i++)
- {
- steer_pl = steer_policies[i];
- pl = pool_elt_at_index (sm->sr_policies, steer_pl->sr_policy);
- if (steer_pl->classify.traffic_type == SR_STEER_L2)
- {
- vlib_cli_output (vm, "L2 %U\t%U",
- format_vnet_sw_if_index_name, vnm,
- steer_pl->classify.l2.sw_if_index,
- format_ip6_address, &pl->bsid);
- }
- else if (steer_pl->classify.traffic_type == SR_STEER_IPV4)
- {
- vlib_cli_output (vm, "L3 %U/%d\t%U",
- format_ip4_address,
- &steer_pl->classify.l3.prefix.ip4,
- steer_pl->classify.l3.mask_width,
- format_ip6_address, &pl->bsid);
- }
- else if (steer_pl->classify.traffic_type == SR_STEER_IPV6)
- {
- vlib_cli_output (vm, "L3 %U/%d\t%U",
- format_ip6_address,
- &steer_pl->classify.l3.prefix.ip6,
- steer_pl->classify.l3.mask_width,
- format_ip6_address, &pl->bsid);
- }
- }
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_sr_steering_policies_command, static) = {
- .path = "show sr steering policies",
- .short_help = "show sr steering policies",
- .function = show_sr_steering_policies_command_fn,
-};
-/* *INDENT-ON* */
-
-clib_error_t *
-sr_steering_init (vlib_main_t * vm)
-{
- ip6_sr_main_t *sm = &sr_main;
-
- /* Init memory for function keys */
- mhash_init (&sm->sr_steer_policies_hash, sizeof (uword),
- sizeof (sr_steering_key_t));
-
- sm->sw_iface_sr_policies = 0;
-
- sm->vnet_main = vnet_get_main ();
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_INIT_FUNCTION (sr_steering_init);
-/* *INDENT-ON* */
-
-/* *INDENT-OFF* */
-VNET_FEATURE_INIT (sr_pl_rewrite_encaps_l2, static) =
-{
- .arc_name = "device-input",
- .node_name = "sr-pl-rewrite-encaps-l2",
- .runs_before = VNET_FEATURES ("ethernet-input"),
-};
-/* *INDENT-ON* */
-
-/*
-* fd.io coding-style-patch-verification: ON
-*
-* Local Variables:
-* eval: (c-set-style "gnu")
-* End:
-*/