/* * 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 #include #include #include #include #include #include #include #include #include /** * @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; clib_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 */ int ret = vnet_feature_enable_disable ("device-input", "sr-pl-rewrite-encaps-l2", sw_if_index, 0, 0, 0); if (ret != 0) return -1; sm->sw_iface_sr_policies[sw_if_index] = ~(u32) 0; /* Remove promiscous mode from interface */ vnet_main_t *vnm = vnet_get_main (); vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index); /* Make sure it is main interface */ if (hi->sw_if_index == sw_if_index) ethernet_set_flags (vnm, hi->hw_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_SOURCE_SR); fib_table_unlock (sm->fib_table_ip4, FIB_PROTOCOL_IP6, FIB_SOURCE_SR); sm->fib_table_ip6 = (u32) ~ 0; sm->fib_table_ip4 = (u32) ~ 0; } return 0; } 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
/*
 * mpls_error.def: mpls errors
 *
 * Copyright (c) 2012 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.
 */

mpls_error (NONE, "no error")
mpls_error (UNKNOWN_PROTOCOL, "unknown protocol")
mpls_error (UNSUPPORTED_VERSION, "unsupported version")
mpls_error (PKTS_DECAP, "MPLS input packets decapsulated")
mpls_error (PKTS_ENCAP, "MPLS output packets encapsulated")
mpls_error (NO_LABEL, "MPLS no label for fib/dst")
mpls_error (TTL_EXPIRED, "MPLS ttl expired")
mpls_error (S_NOT_SET, "MPLS s-bit not set")
mpls_error (BAD_LABEL, "invalid FIB id in label")
mpls_error (NOT_IP4, "non-ip4 packets dropped")
mpls_error (DISALLOWED_FIB, "disallowed FIB id")
mpls_error (NOT_ENABLED, "MPLS not enabled")
mpls_error (DROP, "MPLS DROP DPO")
mpls_error (PUNT, "MPLS PUNT DPO")
->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; } 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, }; 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; } VLIB_INIT_FUNCTION (sr_steering_init); 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"), }; /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */