diff options
Diffstat (limited to 'src/plugins')
49 files changed, 0 insertions, 13942 deletions
diff --git a/src/plugins/gbp/CMakeLists.txt b/src/plugins/gbp/CMakeLists.txt deleted file mode 100644 index 95f664ff08e..00000000000 --- a/src/plugins/gbp/CMakeLists.txt +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2018 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. - -add_vpp_plugin(gbp - SOURCES - gbp_api.c - gbp_bridge_domain.c - gbp_classify.c - gbp_classify_node.c - gbp_contract.c - gbp_endpoint.c - gbp_endpoint_group.c - gbp_ext_itf.c - gbp_fwd.c - gbp_fwd_dpo.c - gbp_fwd_node.c - gbp_itf.c - gbp_learn.c - gbp_learn_node.c - gbp_policy.c - gbp_policy_dpo.c - gbp_policy_node.c - gbp_recirc.c - gbp_route_domain.c - gbp_scanner.c - gbp_subnet.c - gbp_vxlan.c - gbp_vxlan_node.c - - MULTIARCH_SOURCES - gbp_classify_node.c - gbp_fwd_dpo.c - gbp_fwd_node.c - gbp_learn_node.c - gbp_policy_dpo.c - gbp_policy_node.c - gbp_vxlan_node.c - - API_FILES - gbp.api - - INSTALL_HEADERS - gbp.h -) diff --git a/src/plugins/gbp/gbp.api b/src/plugins/gbp/gbp.api deleted file mode 100644 index 525e70536bd..00000000000 --- a/src/plugins/gbp/gbp.api +++ /dev/null @@ -1,470 +0,0 @@ -/* Hey Emacs use -*- mode: C -*- */ -/* - * Copyright (c) 2018 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. - */ - -option version = "2.0.0"; - -import "vnet/ip/ip_types.api"; -import "vnet/ethernet/ethernet_types.api"; -import "vnet/interface_types.api"; - -enum gbp_bridge_domain_flags -{ - GBP_BD_API_FLAG_NONE = 0, - GBP_BD_API_FLAG_DO_NOT_LEARN = 1, - GBP_BD_API_FLAG_UU_FWD_DROP = 2, - GBP_BD_API_FLAG_MCAST_DROP = 4, - GBP_BD_API_FLAG_UCAST_ARP = 8, -}; - -typedef gbp_bridge_domain -{ - u32 bd_id; - u32 rd_id; - vl_api_gbp_bridge_domain_flags_t flags; - vl_api_interface_index_t bvi_sw_if_index; - vl_api_interface_index_t uu_fwd_sw_if_index; - vl_api_interface_index_t bm_flood_sw_if_index; -}; - - autoreply define gbp_bridge_domain_add -{ - option status="in_progress"; - u32 client_index; - u32 context; - vl_api_gbp_bridge_domain_t bd; -}; - autoreply define gbp_bridge_domain_del -{ - option status="in_progress"; - u32 client_index; - u32 context; - u32 bd_id; -}; -autoreply define gbp_bridge_domain_dump -{ - option status="in_progress"; - u32 client_index; - u32 context; -}; -define gbp_bridge_domain_details -{ - option status="in_progress"; - u32 context; - vl_api_gbp_bridge_domain_t bd; -}; - -typedef u16 gbp_scope; - -typedef gbp_route_domain -{ - u32 rd_id; - u32 ip4_table_id; - u32 ip6_table_id; - vl_api_interface_index_t ip4_uu_sw_if_index; - vl_api_interface_index_t ip6_uu_sw_if_index; - vl_api_gbp_scope_t scope; -}; - - autoreply define gbp_route_domain_add -{ - option status="in_progress"; - u32 client_index; - u32 context; - vl_api_gbp_route_domain_t rd; -}; - autoreply define gbp_route_domain_del -{ - option status="in_progress"; - u32 client_index; - u32 context; - u32 rd_id; -}; -autoreply define gbp_route_domain_dump -{ - option status="in_progress"; - u32 client_index; - u32 context; -}; -define gbp_route_domain_details -{ - option status="in_progress"; - u32 context; - vl_api_gbp_route_domain_t rd; -}; - -/** \brief Endpoint - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request -*/ - -enum gbp_endpoint_flags -{ - GBP_API_ENDPOINT_FLAG_NONE = 0, - GBP_API_ENDPOINT_FLAG_BOUNCE = 0x1, - GBP_API_ENDPOINT_FLAG_REMOTE = 0x2, - GBP_API_ENDPOINT_FLAG_LEARNT = 0x4, - GBP_API_ENDPOINT_FLAG_EXTERNAL = 0x8, -}; - -typedef gbp_endpoint_tun -{ - vl_api_address_t src; - vl_api_address_t dst; -}; - -typedef gbp_endpoint -{ - vl_api_interface_index_t sw_if_index; - u16 sclass; - vl_api_gbp_endpoint_flags_t flags; - vl_api_mac_address_t mac; - vl_api_gbp_endpoint_tun_t tun; - u8 n_ips; - vl_api_address_t ips[n_ips]; -}; - - define gbp_endpoint_add -{ - option status="in_progress"; - u32 client_index; - u32 context; - vl_api_gbp_endpoint_t endpoint; -}; - -define gbp_endpoint_add_reply -{ - option status="in_progress"; - u32 context; - i32 retval; - u32 handle; -}; - - autoreply define gbp_endpoint_del -{ - option status="in_progress"; - u32 client_index; - u32 context; - u32 handle; -}; - -define gbp_endpoint_dump -{ - option status="in_progress"; - u32 client_index; - u32 context; -}; - -define gbp_endpoint_details -{ - option status="in_progress"; - u32 context; - f64 age; - u32 handle; - vl_api_gbp_endpoint_t endpoint; -}; - -typedef gbp_endpoint_retention -{ - u32 remote_ep_timeout; -}; - -typedef gbp_endpoint_group -{ - u32 vnid; - u16 sclass; - u32 bd_id; - u32 rd_id; - vl_api_interface_index_t uplink_sw_if_index; - vl_api_gbp_endpoint_retention_t retention; -}; - - autoreply define gbp_endpoint_group_add -{ - option status="in_progress"; - u32 client_index; - u32 context; - vl_api_gbp_endpoint_group_t epg; -}; - autoreply define gbp_endpoint_group_del -{ - option status="in_progress"; - u32 client_index; - u32 context; - u16 sclass; -}; - -define gbp_endpoint_group_dump -{ - option status="in_progress"; - u32 client_index; - u32 context; -}; - -define gbp_endpoint_group_details -{ - option status="in_progress"; - u32 context; - vl_api_gbp_endpoint_group_t epg; -}; - -typedef gbp_recirc -{ - vl_api_interface_index_t sw_if_index; - u16 sclass; - bool is_ext; -}; - - autoreply define gbp_recirc_add_del -{ - option status="in_progress"; - u32 client_index; - u32 context; - bool is_add; - vl_api_gbp_recirc_t recirc; -}; - -define gbp_recirc_dump -{ - option status="in_progress"; - u32 client_index; - u32 context; -}; - -define gbp_recirc_details -{ - option status="in_progress"; - u32 context; - vl_api_gbp_recirc_t recirc; -}; - -enum gbp_subnet_type -{ - GBP_API_SUBNET_TRANSPORT, - GBP_API_SUBNET_STITCHED_INTERNAL, - GBP_API_SUBNET_STITCHED_EXTERNAL, - GBP_API_SUBNET_L3_OUT, - GBP_API_SUBNET_ANON_L3_OUT, -}; - -typedef gbp_subnet -{ - u32 rd_id; - vl_api_interface_index_t sw_if_index [default= 0xffffffff]; - u16 sclass [default=0xffffffff]; - vl_api_gbp_subnet_type_t type; - vl_api_prefix_t prefix; -}; - - autoreply define gbp_subnet_add_del -{ - option status="in_progress"; - u32 client_index; - u32 context; - bool is_add; - vl_api_gbp_subnet_t subnet; -}; - -define gbp_subnet_dump -{ - option status="in_progress"; - u32 client_index; - u32 context; -}; - -define gbp_subnet_details -{ - option status="in_progress"; - u32 context; - vl_api_gbp_subnet_t subnet; -}; - -typedef gbp_next_hop -{ - vl_api_address_t ip; - vl_api_mac_address_t mac; - u32 bd_id; - u32 rd_id; -}; - -enum gbp_hash_mode -{ - GBP_API_HASH_MODE_SRC_IP, - GBP_API_HASH_MODE_DST_IP, - GBP_API_HASH_MODE_SYMMETRIC, -}; - -typedef gbp_next_hop_set -{ - vl_api_gbp_hash_mode_t hash_mode; - u8 n_nhs; - vl_api_gbp_next_hop_t nhs[8]; -}; - -enum gbp_rule_action -{ - GBP_API_RULE_PERMIT, - GBP_API_RULE_DENY, - GBP_API_RULE_REDIRECT, -}; - -typedef gbp_rule -{ - vl_api_gbp_rule_action_t action; - vl_api_gbp_next_hop_set_t nh_set; -}; - -typedef gbp_contract -{ - vl_api_gbp_scope_t scope; - u16 sclass; - u16 dclass; - u32 acl_index; - u8 n_ether_types; - u16 allowed_ethertypes[16]; - u8 n_rules; - vl_api_gbp_rule_t rules[n_rules]; -}; - - define gbp_contract_add_del -{ - option status="in_progress"; - u32 client_index; - u32 context; - bool is_add; - vl_api_gbp_contract_t contract; -}; -define gbp_contract_add_del_reply -{ - option status="in_progress"; - u32 context; - i32 retval; - u32 stats_index; -}; - -define gbp_contract_dump -{ - option status="in_progress"; - u32 client_index; - u32 context; -}; - -define gbp_contract_details -{ - option status="in_progress"; - u32 context; - vl_api_gbp_contract_t contract; -}; - -/** - * @brief Configure a 'base' tunnel from which learned tunnels - * are permitted to derive - * A base tunnel consists only of the VNI, any src,dst IP - * pair is thus allowed. - */ -enum gbp_vxlan_tunnel_mode -{ - GBP_VXLAN_TUNNEL_MODE_L2, - GBP_VXLAN_TUNNEL_MODE_L3, -}; - -typedef gbp_vxlan_tunnel -{ - u32 vni; - vl_api_gbp_vxlan_tunnel_mode_t mode; - u32 bd_rd_id; - vl_api_ip4_address_t src; -}; - - define gbp_vxlan_tunnel_add -{ - option status="in_progress"; - u32 client_index; - u32 context; - vl_api_gbp_vxlan_tunnel_t tunnel; -}; - -define gbp_vxlan_tunnel_add_reply -{ - option status="in_progress"; - u32 context; - i32 retval; - vl_api_interface_index_t sw_if_index; -}; - - autoreply define gbp_vxlan_tunnel_del -{ - option status="in_progress"; - u32 client_index; - u32 context; - u32 vni; -}; - -define gbp_vxlan_tunnel_dump -{ - option status="in_progress"; - u32 client_index; - u32 context; -}; - -define gbp_vxlan_tunnel_details -{ - option status="in_progress"; - u32 context; - vl_api_gbp_vxlan_tunnel_t tunnel; -}; - -enum gbp_ext_itf_flags -{ - GBP_API_EXT_ITF_F_NONE = 0, - GBP_API_EXT_ITF_F_ANON = 1, -}; - -typedef gbp_ext_itf -{ - vl_api_interface_index_t sw_if_index; - u32 bd_id; - u32 rd_id; - vl_api_gbp_ext_itf_flags_t flags; -}; - - autoreply define gbp_ext_itf_add_del -{ - option status="in_progress"; - u32 client_index; - u32 context; - bool is_add; - vl_api_gbp_ext_itf_t ext_itf; -}; - -define gbp_ext_itf_dump -{ - option status="in_progress"; - u32 client_index; - u32 context; -}; - -define gbp_ext_itf_details -{ - option status="in_progress"; - u32 context; - vl_api_gbp_ext_itf_t ext_itf; -}; - -/* - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp.h b/src/plugins/gbp/gbp.h deleted file mode 100644 index 50039b3bdcf..00000000000 --- a/src/plugins/gbp/gbp.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -/** - * Group Base Policy (GBP) defines: - * - endpoints: typically a VM or container that is connected to the - * virtual switch/router (i.e. to VPP) - * - endpoint-group: (EPG) a collection of endpoints - * - policy: rules determining which traffic can pass between EPGs a.k.a - * a 'contract' - * - * Here, policy is implemented via an ACL. - * EPG classification for transit packets is determined by: - * - source EPG: from the packet's input interface - * - destination EPG: from the packet's destination IP address. - * - */ - -#ifndef __GBP_H__ -#define __GBP_H__ - -#include <plugins/acl/exports.h> - -#include <plugins/gbp/gbp_types.h> -#include <plugins/gbp/gbp_endpoint.h> -#include <plugins/gbp/gbp_endpoint_group.h> -#include <plugins/gbp/gbp_subnet.h> -#include <plugins/gbp/gbp_recirc.h> - -typedef struct -{ - u32 gbp_acl_user_id; - acl_plugin_methods_t acl_plugin; -} gbp_main_t; - -extern gbp_main_t gbp_main; - -typedef enum gbp_policy_type_t_ -{ - GBP_POLICY_PORT, - GBP_POLICY_MAC, - GBP_POLICY_LPM, - GBP_N_POLICY -#define GBP_N_POLICY GBP_N_POLICY -} gbp_policy_type_t; - -/** - * Grouping of global data for the GBP source EPG classification feature - */ -typedef struct gbp_policy_main_t_ -{ - /** - * Next nodes for L2 output features - */ - u32 l2_output_feat_next[GBP_N_POLICY][32]; -} gbp_policy_main_t; - -extern gbp_policy_main_t gbp_policy_main; - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_api.c b/src/plugins/gbp/gbp_api.c deleted file mode 100644 index ab89172b1af..00000000000 --- a/src/plugins/gbp/gbp_api.c +++ /dev/null @@ -1,1154 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 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. - *------------------------------------------------------------------ - */ - -#include <vnet/vnet.h> -#include <vnet/plugin/plugin.h> - -#include <vnet/interface.h> -#include <vnet/api_errno.h> -#include <vnet/ip/ip_types_api.h> -#include <vnet/ethernet/ethernet_types_api.h> -#include <vpp/app/version.h> - -#include <gbp/gbp.h> -#include <gbp/gbp_learn.h> -#include <gbp/gbp_itf.h> -#include <gbp/gbp_vxlan.h> -#include <gbp/gbp_bridge_domain.h> -#include <gbp/gbp_route_domain.h> -#include <gbp/gbp_ext_itf.h> -#include <gbp/gbp_contract.h> - -#include <vlibapi/api.h> -#include <vlibmemory/api.h> - -/* define message IDs */ -#include <gbp/gbp.api_enum.h> -#include <gbp/gbp.api_types.h> -#include <vnet/format_fns.h> -#include <vlibapi/api_helper_macros.h> -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) - -gbp_main_t gbp_main; - -static u16 msg_id_base; - -#define GBP_MSG_BASE msg_id_base - -static gbp_endpoint_flags_t -gbp_endpoint_flags_decode (vl_api_gbp_endpoint_flags_t v) -{ - gbp_endpoint_flags_t f = GBP_ENDPOINT_FLAG_NONE; - - v = ntohl (v); - - if (v & GBP_API_ENDPOINT_FLAG_BOUNCE) - f |= GBP_ENDPOINT_FLAG_BOUNCE; - if (v & GBP_API_ENDPOINT_FLAG_REMOTE) - f |= GBP_ENDPOINT_FLAG_REMOTE; - if (v & GBP_API_ENDPOINT_FLAG_LEARNT) - f |= GBP_ENDPOINT_FLAG_LEARNT; - if (v & GBP_API_ENDPOINT_FLAG_EXTERNAL) - f |= GBP_ENDPOINT_FLAG_EXTERNAL; - - return (f); -} - -static vl_api_gbp_endpoint_flags_t -gbp_endpoint_flags_encode (gbp_endpoint_flags_t f) -{ - vl_api_gbp_endpoint_flags_t v = 0; - - - if (f & GBP_ENDPOINT_FLAG_BOUNCE) - v |= GBP_API_ENDPOINT_FLAG_BOUNCE; - if (f & GBP_ENDPOINT_FLAG_REMOTE) - v |= GBP_API_ENDPOINT_FLAG_REMOTE; - if (f & GBP_ENDPOINT_FLAG_LEARNT) - v |= GBP_API_ENDPOINT_FLAG_LEARNT; - if (f & GBP_ENDPOINT_FLAG_EXTERNAL) - v |= GBP_API_ENDPOINT_FLAG_EXTERNAL; - - v = htonl (v); - - return (v); -} - -static void -vl_api_gbp_endpoint_add_t_handler (vl_api_gbp_endpoint_add_t * mp) -{ - vl_api_gbp_endpoint_add_reply_t *rmp; - gbp_endpoint_flags_t gef; - u32 sw_if_index, handle; - ip46_address_t *ips; - mac_address_t mac; - int rv = 0, ii; - - handle = INDEX_INVALID; - - VALIDATE_SW_IF_INDEX (&(mp->endpoint)); - - gef = gbp_endpoint_flags_decode (mp->endpoint.flags), ips = NULL; - sw_if_index = ntohl (mp->endpoint.sw_if_index); - - if (mp->endpoint.n_ips) - { - vec_validate (ips, mp->endpoint.n_ips - 1); - - vec_foreach_index (ii, ips) - { - ip_address_decode (&mp->endpoint.ips[ii], &ips[ii]); - } - } - mac_address_decode (mp->endpoint.mac, &mac); - - if (GBP_ENDPOINT_FLAG_REMOTE & gef) - { - ip46_address_t tun_src, tun_dst; - - ip_address_decode (&mp->endpoint.tun.src, &tun_src); - ip_address_decode (&mp->endpoint.tun.dst, &tun_dst); - - rv = gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_CP, - sw_if_index, ips, &mac, - INDEX_INVALID, INDEX_INVALID, - ntohs (mp->endpoint.sclass), - gef, &tun_src, &tun_dst, &handle); - } - else - { - rv = gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_CP, - sw_if_index, ips, &mac, - INDEX_INVALID, INDEX_INVALID, - ntohs (mp->endpoint.sclass), - gef, NULL, NULL, &handle); - } - vec_free (ips); - BAD_SW_IF_INDEX_LABEL; - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_GBP_ENDPOINT_ADD_REPLY + GBP_MSG_BASE, - ({ - rmp->handle = htonl (handle); - })); - /* *INDENT-ON* */ -} - -static void -vl_api_gbp_endpoint_del_t_handler (vl_api_gbp_endpoint_del_t * mp) -{ - vl_api_gbp_endpoint_del_reply_t *rmp; - int rv = 0; - - gbp_endpoint_unlock (GBP_ENDPOINT_SRC_CP, ntohl (mp->handle)); - - REPLY_MACRO (VL_API_GBP_ENDPOINT_DEL_REPLY + GBP_MSG_BASE); -} - -typedef struct gbp_walk_ctx_t_ -{ - vl_api_registration_t *reg; - u32 context; -} gbp_walk_ctx_t; - -static walk_rc_t -gbp_endpoint_send_details (index_t gei, void *args) -{ - vl_api_gbp_endpoint_details_t *mp; - gbp_endpoint_loc_t *gel; - gbp_endpoint_fwd_t *gef; - gbp_endpoint_t *ge; - gbp_walk_ctx_t *ctx; - u8 n_ips, ii; - - ctx = args; - ge = gbp_endpoint_get (gei); - - n_ips = vec_len (ge->ge_key.gek_ips); - mp = vl_msg_api_alloc (sizeof (*mp) + (sizeof (*mp->endpoint.ips) * n_ips)); - if (!mp) - return 1; - - clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_GBP_ENDPOINT_DETAILS + GBP_MSG_BASE); - mp->context = ctx->context; - - gel = &ge->ge_locs[0]; - gef = &ge->ge_fwd; - - if (gbp_endpoint_is_remote (ge)) - { - mp->endpoint.sw_if_index = ntohl (gel->tun.gel_parent_sw_if_index); - ip_address_encode (&gel->tun.gel_src, IP46_TYPE_ANY, - &mp->endpoint.tun.src); - ip_address_encode (&gel->tun.gel_dst, IP46_TYPE_ANY, - &mp->endpoint.tun.dst); - } - else - { - mp->endpoint.sw_if_index = - ntohl (gbp_itf_get_sw_if_index (gef->gef_itf)); - } - mp->endpoint.sclass = ntohs (ge->ge_fwd.gef_sclass); - mp->endpoint.n_ips = n_ips; - mp->endpoint.flags = gbp_endpoint_flags_encode (gef->gef_flags); - mp->handle = htonl (gei); - mp->age = - clib_host_to_net_f64 (vlib_time_now (vlib_get_main ()) - - ge->ge_last_time); - mac_address_encode (&ge->ge_key.gek_mac, mp->endpoint.mac); - - vec_foreach_index (ii, ge->ge_key.gek_ips) - { - ip_address_encode (&ge->ge_key.gek_ips[ii].fp_addr, - IP46_TYPE_ANY, &mp->endpoint.ips[ii]); - } - - vl_api_send_msg (ctx->reg, (u8 *) mp); - - return (WALK_CONTINUE); -} - -static void -vl_api_gbp_endpoint_dump_t_handler (vl_api_gbp_endpoint_dump_t * mp) -{ - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - gbp_walk_ctx_t ctx = { - .reg = reg, - .context = mp->context, - }; - - gbp_endpoint_walk (gbp_endpoint_send_details, &ctx); -} - -static void -gbp_retention_decode (const vl_api_gbp_endpoint_retention_t * in, - gbp_endpoint_retention_t * out) -{ - out->remote_ep_timeout = ntohl (in->remote_ep_timeout); -} - -static void - vl_api_gbp_endpoint_group_add_t_handler - (vl_api_gbp_endpoint_group_add_t * mp) -{ - vl_api_gbp_endpoint_group_add_reply_t *rmp; - gbp_endpoint_retention_t retention; - int rv = 0; - - gbp_retention_decode (&mp->epg.retention, &retention); - - rv = gbp_endpoint_group_add_and_lock (ntohl (mp->epg.vnid), - ntohs (mp->epg.sclass), - ntohl (mp->epg.bd_id), - ntohl (mp->epg.rd_id), - ntohl (mp->epg.uplink_sw_if_index), - &retention); - - REPLY_MACRO (VL_API_GBP_ENDPOINT_GROUP_ADD_REPLY + GBP_MSG_BASE); -} - -static void - vl_api_gbp_endpoint_group_del_t_handler - (vl_api_gbp_endpoint_group_del_t * mp) -{ - vl_api_gbp_endpoint_group_del_reply_t *rmp; - int rv = 0; - - rv = gbp_endpoint_group_delete (ntohs (mp->sclass)); - - REPLY_MACRO (VL_API_GBP_ENDPOINT_GROUP_DEL_REPLY + GBP_MSG_BASE); -} - -static gbp_bridge_domain_flags_t -gbp_bridge_domain_flags_from_api (vl_api_gbp_bridge_domain_flags_t a) -{ - gbp_bridge_domain_flags_t g; - - g = GBP_BD_FLAG_NONE; - a = clib_net_to_host_u32 (a); - - if (a & GBP_BD_API_FLAG_DO_NOT_LEARN) - g |= GBP_BD_FLAG_DO_NOT_LEARN; - if (a & GBP_BD_API_FLAG_UU_FWD_DROP) - g |= GBP_BD_FLAG_UU_FWD_DROP; - if (a & GBP_BD_API_FLAG_MCAST_DROP) - g |= GBP_BD_FLAG_MCAST_DROP; - if (a & GBP_BD_API_FLAG_UCAST_ARP) - g |= GBP_BD_FLAG_UCAST_ARP; - - return (g); -} - -static void -vl_api_gbp_bridge_domain_add_t_handler (vl_api_gbp_bridge_domain_add_t * mp) -{ - vl_api_gbp_bridge_domain_add_reply_t *rmp; - int rv = 0; - - rv = gbp_bridge_domain_add_and_lock (ntohl (mp->bd.bd_id), - ntohl (mp->bd.rd_id), - gbp_bridge_domain_flags_from_api - (mp->bd.flags), - ntohl (mp->bd.bvi_sw_if_index), - ntohl (mp->bd.uu_fwd_sw_if_index), - ntohl (mp->bd.bm_flood_sw_if_index)); - - REPLY_MACRO (VL_API_GBP_BRIDGE_DOMAIN_ADD_REPLY + GBP_MSG_BASE); -} - -static void -vl_api_gbp_bridge_domain_del_t_handler (vl_api_gbp_bridge_domain_del_t * mp) -{ - vl_api_gbp_bridge_domain_del_reply_t *rmp; - int rv = 0; - - rv = gbp_bridge_domain_delete (ntohl (mp->bd_id)); - - REPLY_MACRO (VL_API_GBP_BRIDGE_DOMAIN_DEL_REPLY + GBP_MSG_BASE); -} - -static void -vl_api_gbp_route_domain_add_t_handler (vl_api_gbp_route_domain_add_t * mp) -{ - vl_api_gbp_route_domain_add_reply_t *rmp; - int rv = 0; - - rv = gbp_route_domain_add_and_lock (ntohl (mp->rd.rd_id), - ntohs (mp->rd.scope), - ntohl (mp->rd.ip4_table_id), - ntohl (mp->rd.ip6_table_id), - ntohl (mp->rd.ip4_uu_sw_if_index), - ntohl (mp->rd.ip6_uu_sw_if_index)); - - REPLY_MACRO (VL_API_GBP_ROUTE_DOMAIN_ADD_REPLY + GBP_MSG_BASE); -} - -static void -vl_api_gbp_route_domain_del_t_handler (vl_api_gbp_route_domain_del_t * mp) -{ - vl_api_gbp_route_domain_del_reply_t *rmp; - int rv = 0; - - rv = gbp_route_domain_delete (ntohl (mp->rd_id)); - - REPLY_MACRO (VL_API_GBP_ROUTE_DOMAIN_DEL_REPLY + GBP_MSG_BASE); -} - -static int -gub_subnet_type_from_api (vl_api_gbp_subnet_type_t a, gbp_subnet_type_t * t) -{ - a = clib_net_to_host_u32 (a); - - switch (a) - { - case GBP_API_SUBNET_TRANSPORT: - *t = GBP_SUBNET_TRANSPORT; - return (0); - case GBP_API_SUBNET_L3_OUT: - *t = GBP_SUBNET_L3_OUT; - return (0); - case GBP_API_SUBNET_ANON_L3_OUT: - *t = GBP_SUBNET_ANON_L3_OUT; - return (0); - case GBP_API_SUBNET_STITCHED_INTERNAL: - *t = GBP_SUBNET_STITCHED_INTERNAL; - return (0); - case GBP_API_SUBNET_STITCHED_EXTERNAL: - *t = GBP_SUBNET_STITCHED_EXTERNAL; - return (0); - } - - return (-1); -} - -static void -vl_api_gbp_subnet_add_del_t_handler (vl_api_gbp_subnet_add_del_t * mp) -{ - vl_api_gbp_subnet_add_del_reply_t *rmp; - gbp_subnet_type_t type; - fib_prefix_t pfx; - int rv = 0; - - ip_prefix_decode (&mp->subnet.prefix, &pfx); - - rv = gub_subnet_type_from_api (mp->subnet.type, &type); - - if (0 != rv) - goto out; - - if (mp->is_add) - rv = gbp_subnet_add (ntohl (mp->subnet.rd_id), - &pfx, type, - ntohl (mp->subnet.sw_if_index), - ntohs (mp->subnet.sclass)); - else - rv = gbp_subnet_del (ntohl (mp->subnet.rd_id), &pfx); - -out: - REPLY_MACRO (VL_API_GBP_SUBNET_ADD_DEL_REPLY + GBP_MSG_BASE); -} - -static vl_api_gbp_subnet_type_t -gub_subnet_type_to_api (gbp_subnet_type_t t) -{ - vl_api_gbp_subnet_type_t a = 0; - - switch (t) - { - case GBP_SUBNET_TRANSPORT: - a = GBP_API_SUBNET_TRANSPORT; - break; - case GBP_SUBNET_STITCHED_INTERNAL: - a = GBP_API_SUBNET_STITCHED_INTERNAL; - break; - case GBP_SUBNET_STITCHED_EXTERNAL: - a = GBP_API_SUBNET_STITCHED_EXTERNAL; - break; - case GBP_SUBNET_L3_OUT: - a = GBP_API_SUBNET_L3_OUT; - break; - case GBP_SUBNET_ANON_L3_OUT: - a = GBP_API_SUBNET_ANON_L3_OUT; - break; - } - - a = clib_host_to_net_u32 (a); - - return (a); -} - -static walk_rc_t -gbp_subnet_send_details (u32 rd_id, - const fib_prefix_t * pfx, - gbp_subnet_type_t type, - u32 sw_if_index, sclass_t sclass, void *args) -{ - vl_api_gbp_subnet_details_t *mp; - gbp_walk_ctx_t *ctx; - - ctx = args; - mp = vl_msg_api_alloc (sizeof (*mp)); - if (!mp) - return 1; - - clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_GBP_SUBNET_DETAILS + GBP_MSG_BASE); - mp->context = ctx->context; - - mp->subnet.type = gub_subnet_type_to_api (type); - mp->subnet.sw_if_index = ntohl (sw_if_index); - mp->subnet.sclass = ntohs (sclass); - mp->subnet.rd_id = ntohl (rd_id); - ip_prefix_encode (pfx, &mp->subnet.prefix); - - vl_api_send_msg (ctx->reg, (u8 *) mp); - - return (WALK_CONTINUE); -} - -static void -vl_api_gbp_subnet_dump_t_handler (vl_api_gbp_subnet_dump_t * mp) -{ - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - gbp_walk_ctx_t ctx = { - .reg = reg, - .context = mp->context, - }; - - gbp_subnet_walk (gbp_subnet_send_details, &ctx); -} - -static int -gbp_endpoint_group_send_details (gbp_endpoint_group_t * gg, void *args) -{ - vl_api_gbp_endpoint_group_details_t *mp; - gbp_walk_ctx_t *ctx; - - ctx = args; - mp = vl_msg_api_alloc (sizeof (*mp)); - if (!mp) - return 1; - - clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_GBP_ENDPOINT_GROUP_DETAILS + GBP_MSG_BASE); - mp->context = ctx->context; - - mp->epg.uplink_sw_if_index = ntohl (gg->gg_uplink_sw_if_index); - mp->epg.vnid = ntohl (gg->gg_vnid); - mp->epg.sclass = ntohs (gg->gg_sclass); - mp->epg.bd_id = ntohl (gbp_endpoint_group_get_bd_id (gg)); - mp->epg.rd_id = ntohl (gbp_route_domain_get_rd_id (gg->gg_rd)); - - vl_api_send_msg (ctx->reg, (u8 *) mp); - - return (1); -} - -static void -vl_api_gbp_endpoint_group_dump_t_handler (vl_api_gbp_endpoint_group_dump_t * - mp) -{ - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - gbp_walk_ctx_t ctx = { - .reg = reg, - .context = mp->context, - }; - - gbp_endpoint_group_walk (gbp_endpoint_group_send_details, &ctx); -} - -static int -gbp_bridge_domain_send_details (gbp_bridge_domain_t * gb, void *args) -{ - vl_api_gbp_bridge_domain_details_t *mp; - gbp_route_domain_t *gr; - gbp_walk_ctx_t *ctx; - - ctx = args; - mp = vl_msg_api_alloc (sizeof (*mp)); - if (!mp) - return 1; - - memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_GBP_BRIDGE_DOMAIN_DETAILS + GBP_MSG_BASE); - mp->context = ctx->context; - - gr = gbp_route_domain_get (gb->gb_rdi); - - mp->bd.bd_id = ntohl (gb->gb_bd_id); - mp->bd.rd_id = ntohl (gr->grd_id); - mp->bd.bvi_sw_if_index = ntohl (gb->gb_bvi_sw_if_index); - mp->bd.uu_fwd_sw_if_index = ntohl (gb->gb_uu_fwd_sw_if_index); - mp->bd.bm_flood_sw_if_index = - ntohl (gbp_itf_get_sw_if_index (gb->gb_bm_flood_itf)); - - vl_api_send_msg (ctx->reg, (u8 *) mp); - - return (1); -} - -static void -vl_api_gbp_bridge_domain_dump_t_handler (vl_api_gbp_bridge_domain_dump_t * mp) -{ - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - gbp_walk_ctx_t ctx = { - .reg = reg, - .context = mp->context, - }; - - gbp_bridge_domain_walk (gbp_bridge_domain_send_details, &ctx); -} - -static int -gbp_route_domain_send_details (gbp_route_domain_t * grd, void *args) -{ - vl_api_gbp_route_domain_details_t *mp; - gbp_walk_ctx_t *ctx; - - ctx = args; - mp = vl_msg_api_alloc (sizeof (*mp)); - if (!mp) - return 1; - - memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_GBP_ROUTE_DOMAIN_DETAILS + GBP_MSG_BASE); - mp->context = ctx->context; - - mp->rd.rd_id = ntohl (grd->grd_id); - mp->rd.ip4_uu_sw_if_index = - ntohl (grd->grd_uu_sw_if_index[FIB_PROTOCOL_IP4]); - mp->rd.ip6_uu_sw_if_index = - ntohl (grd->grd_uu_sw_if_index[FIB_PROTOCOL_IP6]); - - vl_api_send_msg (ctx->reg, (u8 *) mp); - - return (1); -} - -static void -vl_api_gbp_route_domain_dump_t_handler (vl_api_gbp_route_domain_dump_t * mp) -{ - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - gbp_walk_ctx_t ctx = { - .reg = reg, - .context = mp->context, - }; - - gbp_route_domain_walk (gbp_route_domain_send_details, &ctx); -} - -static void -vl_api_gbp_recirc_add_del_t_handler (vl_api_gbp_recirc_add_del_t * mp) -{ - vl_api_gbp_recirc_add_del_reply_t *rmp; - u32 sw_if_index; - int rv = 0; - - sw_if_index = ntohl (mp->recirc.sw_if_index); - if (!vnet_sw_if_index_is_api_valid (sw_if_index)) - goto bad_sw_if_index; - - if (mp->is_add) - rv = gbp_recirc_add (sw_if_index, - ntohs (mp->recirc.sclass), mp->recirc.is_ext); - else - rv = gbp_recirc_delete (sw_if_index); - - BAD_SW_IF_INDEX_LABEL; - - REPLY_MACRO (VL_API_GBP_RECIRC_ADD_DEL_REPLY + GBP_MSG_BASE); -} - -static walk_rc_t -gbp_recirc_send_details (gbp_recirc_t * gr, void *args) -{ - vl_api_gbp_recirc_details_t *mp; - gbp_walk_ctx_t *ctx; - - ctx = args; - mp = vl_msg_api_alloc (sizeof (*mp)); - if (!mp) - return (WALK_STOP); - - clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_GBP_RECIRC_DETAILS + GBP_MSG_BASE); - mp->context = ctx->context; - - mp->recirc.sclass = ntohs (gr->gr_sclass); - mp->recirc.sw_if_index = ntohl (gr->gr_sw_if_index); - mp->recirc.is_ext = gr->gr_is_ext; - - vl_api_send_msg (ctx->reg, (u8 *) mp); - - return (WALK_CONTINUE); -} - -static void -vl_api_gbp_recirc_dump_t_handler (vl_api_gbp_recirc_dump_t * mp) -{ - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - gbp_walk_ctx_t ctx = { - .reg = reg, - .context = mp->context, - }; - - gbp_recirc_walk (gbp_recirc_send_details, &ctx); -} - -static void -vl_api_gbp_ext_itf_add_del_t_handler (vl_api_gbp_ext_itf_add_del_t * mp) -{ - vl_api_gbp_ext_itf_add_del_reply_t *rmp; - u32 sw_if_index = ~0; - vl_api_gbp_ext_itf_t *ext_itf; - int rv = 0; - - ext_itf = &mp->ext_itf; - if (ext_itf) - sw_if_index = ntohl (ext_itf->sw_if_index); - - if (!vnet_sw_if_index_is_api_valid (sw_if_index)) - goto bad_sw_if_index; - - if (mp->is_add) - rv = gbp_ext_itf_add (sw_if_index, - ntohl (ext_itf->bd_id), ntohl (ext_itf->rd_id), - ntohl (ext_itf->flags)); - else - rv = gbp_ext_itf_delete (sw_if_index); - - BAD_SW_IF_INDEX_LABEL; - - REPLY_MACRO (VL_API_GBP_EXT_ITF_ADD_DEL_REPLY + GBP_MSG_BASE); -} - -static walk_rc_t -gbp_ext_itf_send_details (gbp_ext_itf_t * gx, void *args) -{ - vl_api_gbp_ext_itf_details_t *mp; - gbp_walk_ctx_t *ctx; - - ctx = args; - mp = vl_msg_api_alloc (sizeof (*mp)); - if (!mp) - return (WALK_STOP); - - clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_GBP_EXT_ITF_DETAILS + GBP_MSG_BASE); - mp->context = ctx->context; - - mp->ext_itf.flags = ntohl (gx->gx_flags); - mp->ext_itf.bd_id = ntohl (gbp_bridge_domain_get_bd_id (gx->gx_bd)); - mp->ext_itf.rd_id = ntohl (gbp_route_domain_get_rd_id (gx->gx_rd)); - mp->ext_itf.sw_if_index = ntohl (gbp_itf_get_sw_if_index (gx->gx_itf)); - - vl_api_send_msg (ctx->reg, (u8 *) mp); - - return (WALK_CONTINUE); -} - -static void -vl_api_gbp_ext_itf_dump_t_handler (vl_api_gbp_ext_itf_dump_t * mp) -{ - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - gbp_walk_ctx_t ctx = { - .reg = reg, - .context = mp->context, - }; - - gbp_ext_itf_walk (gbp_ext_itf_send_details, &ctx); -} - -static int -gbp_contract_rule_action_deocde (vl_api_gbp_rule_action_t in, - gbp_rule_action_t * out) -{ - in = clib_net_to_host_u32 (in); - - switch (in) - { - case GBP_API_RULE_PERMIT: - *out = GBP_RULE_PERMIT; - return (0); - case GBP_API_RULE_DENY: - *out = GBP_RULE_DENY; - return (0); - case GBP_API_RULE_REDIRECT: - *out = GBP_RULE_REDIRECT; - return (0); - } - - return (-1); -} - -static int -gbp_hash_mode_decode (vl_api_gbp_hash_mode_t in, gbp_hash_mode_t * out) -{ - in = clib_net_to_host_u32 (in); - - switch (in) - { - case GBP_API_HASH_MODE_SRC_IP: - *out = GBP_HASH_MODE_SRC_IP; - return (0); - case GBP_API_HASH_MODE_DST_IP: - *out = GBP_HASH_MODE_DST_IP; - return (0); - case GBP_API_HASH_MODE_SYMMETRIC: - *out = GBP_HASH_MODE_SYMMETRIC; - return (0); - } - - return (-2); -} - -static int -gbp_next_hop_decode (const vl_api_gbp_next_hop_t * in, index_t * gnhi) -{ - ip46_address_t ip; - mac_address_t mac; - index_t grd, gbd; - - gbd = gbp_bridge_domain_find_and_lock (ntohl (in->bd_id)); - - if (INDEX_INVALID == gbd) - return (VNET_API_ERROR_BD_NOT_MODIFIABLE); - - grd = gbp_route_domain_find_and_lock (ntohl (in->rd_id)); - - if (INDEX_INVALID == grd) - return (VNET_API_ERROR_NO_SUCH_FIB); - - ip_address_decode (&in->ip, &ip); - mac_address_decode (in->mac, &mac); - - *gnhi = gbp_next_hop_alloc (&ip, grd, &mac, gbd); - - return (0); -} - -static int -gbp_next_hop_set_decode (const vl_api_gbp_next_hop_set_t * in, - gbp_hash_mode_t * hash_mode, index_t ** out) -{ - - index_t *gnhis = NULL; - int rv; - u8 ii; - - rv = gbp_hash_mode_decode (in->hash_mode, hash_mode); - - if (0 != rv) - return rv; - - vec_validate (gnhis, in->n_nhs - 1); - - for (ii = 0; ii < in->n_nhs; ii++) - { - rv = gbp_next_hop_decode (&in->nhs[ii], &gnhis[ii]); - - if (0 != rv) - { - vec_free (gnhis); - break; - } - } - - *out = gnhis; - return (rv); -} - -static int -gbp_contract_rule_decode (const vl_api_gbp_rule_t * in, index_t * gui) -{ - gbp_hash_mode_t hash_mode; - gbp_rule_action_t action; - index_t *nhs = NULL; - int rv; - - rv = gbp_contract_rule_action_deocde (in->action, &action); - - if (0 != rv) - return rv; - - if (GBP_RULE_REDIRECT == action) - { - rv = gbp_next_hop_set_decode (&in->nh_set, &hash_mode, &nhs); - - if (0 != rv) - return (rv); - } - else - { - hash_mode = GBP_HASH_MODE_SRC_IP; - } - - *gui = gbp_rule_alloc (action, hash_mode, nhs); - - return (rv); -} - -static int -gbp_contract_rules_decode (u8 n_rules, - const vl_api_gbp_rule_t * rules, index_t ** out) -{ - index_t *guis = NULL; - int rv; - u8 ii; - - if (0 == n_rules) - { - *out = NULL; - return (0); - } - - vec_validate (guis, n_rules - 1); - - for (ii = 0; ii < n_rules; ii++) - { - rv = gbp_contract_rule_decode (&rules[ii], &guis[ii]); - - if (0 != rv) - { - index_t *gui; - vec_foreach (gui, guis) gbp_rule_free (*gui); - vec_free (guis); - return (rv); - } - } - - *out = guis; - return (rv); -} - -static void -vl_api_gbp_contract_add_del_t_handler (vl_api_gbp_contract_add_del_t * mp) -{ - vl_api_gbp_contract_add_del_reply_t *rmp; - u16 *allowed_ethertypes; - u32 stats_index = ~0; - index_t *rules; - int ii, rv = 0; - u8 n_et; - - if (mp->is_add) - { - rv = gbp_contract_rules_decode (mp->contract.n_rules, - mp->contract.rules, &rules); - if (0 != rv) - goto out; - - allowed_ethertypes = NULL; - - /* - * allowed ether types - */ - n_et = mp->contract.n_ether_types; - vec_validate (allowed_ethertypes, n_et - 1); - - for (ii = 0; ii < n_et; ii++) - { - /* leave the ether types in network order */ - allowed_ethertypes[ii] = mp->contract.allowed_ethertypes[ii]; - } - - rv = gbp_contract_update (ntohs (mp->contract.scope), - ntohs (mp->contract.sclass), - ntohs (mp->contract.dclass), - ntohl (mp->contract.acl_index), - rules, allowed_ethertypes, &stats_index); - } - else - rv = gbp_contract_delete (ntohs (mp->contract.scope), - ntohs (mp->contract.sclass), - ntohs (mp->contract.dclass)); - -out: - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_GBP_CONTRACT_ADD_DEL_REPLY + GBP_MSG_BASE, - ({ - rmp->stats_index = htonl (stats_index); - })); - /* *INDENT-ON* */ -} - -static int -gbp_contract_send_details (gbp_contract_t * gbpc, void *args) -{ - vl_api_gbp_contract_details_t *mp; - gbp_walk_ctx_t *ctx; - - ctx = args; - mp = vl_msg_api_alloc (sizeof (*mp)); - if (!mp) - return 1; - - clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_GBP_CONTRACT_DETAILS + GBP_MSG_BASE); - mp->context = ctx->context; - - mp->contract.sclass = ntohs (gbpc->gc_key.gck_src); - mp->contract.dclass = ntohs (gbpc->gc_key.gck_dst); - mp->contract.acl_index = ntohl (gbpc->gc_acl_index); - mp->contract.scope = ntohs (gbpc->gc_key.gck_scope); - - vl_api_send_msg (ctx->reg, (u8 *) mp); - - return (1); -} - -static void -vl_api_gbp_contract_dump_t_handler (vl_api_gbp_contract_dump_t * mp) -{ - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - gbp_walk_ctx_t ctx = { - .reg = reg, - .context = mp->context, - }; - - gbp_contract_walk (gbp_contract_send_details, &ctx); -} - -static int -gbp_vxlan_tunnel_mode_2_layer (vl_api_gbp_vxlan_tunnel_mode_t mode, - gbp_vxlan_tunnel_layer_t * l) -{ - mode = clib_net_to_host_u32 (mode); - - switch (mode) - { - case GBP_VXLAN_TUNNEL_MODE_L2: - *l = GBP_VXLAN_TUN_L2; - return (0); - case GBP_VXLAN_TUNNEL_MODE_L3: - *l = GBP_VXLAN_TUN_L3; - return (0); - } - return (-1); -} - -static void -vl_api_gbp_vxlan_tunnel_add_t_handler (vl_api_gbp_vxlan_tunnel_add_t * mp) -{ - vl_api_gbp_vxlan_tunnel_add_reply_t *rmp; - gbp_vxlan_tunnel_layer_t layer; - ip4_address_t src; - u32 sw_if_index; - int rv = 0; - - ip4_address_decode (mp->tunnel.src, &src); - rv = gbp_vxlan_tunnel_mode_2_layer (mp->tunnel.mode, &layer); - - if (0 != rv) - goto out; - - rv = gbp_vxlan_tunnel_add (ntohl (mp->tunnel.vni), - layer, - ntohl (mp->tunnel.bd_rd_id), &src, &sw_if_index); - -out: - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_GBP_VXLAN_TUNNEL_ADD_REPLY + GBP_MSG_BASE, - ({ - rmp->sw_if_index = htonl (sw_if_index); - })); - /* *INDENT-ON* */ -} - -static void -vl_api_gbp_vxlan_tunnel_del_t_handler (vl_api_gbp_vxlan_tunnel_add_t * mp) -{ - vl_api_gbp_vxlan_tunnel_del_reply_t *rmp; - int rv = 0; - - rv = gbp_vxlan_tunnel_del (ntohl (mp->tunnel.vni)); - - REPLY_MACRO (VL_API_GBP_VXLAN_TUNNEL_DEL_REPLY + GBP_MSG_BASE); -} - -static vl_api_gbp_vxlan_tunnel_mode_t -gbp_vxlan_tunnel_layer_2_mode (gbp_vxlan_tunnel_layer_t layer) -{ - vl_api_gbp_vxlan_tunnel_mode_t mode = GBP_VXLAN_TUNNEL_MODE_L2; - - switch (layer) - { - case GBP_VXLAN_TUN_L2: - mode = GBP_VXLAN_TUNNEL_MODE_L2; - break; - case GBP_VXLAN_TUN_L3: - mode = GBP_VXLAN_TUNNEL_MODE_L3; - break; - } - mode = clib_host_to_net_u32 (mode); - - return (mode); -} - -static walk_rc_t -gbp_vxlan_tunnel_send_details (gbp_vxlan_tunnel_t * gt, void *args) -{ - vl_api_gbp_vxlan_tunnel_details_t *mp; - gbp_walk_ctx_t *ctx; - - ctx = args; - mp = vl_msg_api_alloc (sizeof (*mp)); - if (!mp) - return 1; - - memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = htons (VL_API_GBP_VXLAN_TUNNEL_DETAILS + GBP_MSG_BASE); - mp->context = ctx->context; - - mp->tunnel.vni = htonl (gt->gt_vni); - mp->tunnel.mode = gbp_vxlan_tunnel_layer_2_mode (gt->gt_layer); - mp->tunnel.bd_rd_id = htonl (gt->gt_bd_rd_id); - - vl_api_send_msg (ctx->reg, (u8 *) mp); - - return (1); -} - -static void -vl_api_gbp_vxlan_tunnel_dump_t_handler (vl_api_gbp_vxlan_tunnel_dump_t * mp) -{ - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - gbp_walk_ctx_t ctx = { - .reg = reg, - .context = mp->context, - }; - - gbp_vxlan_walk (gbp_vxlan_tunnel_send_details, &ctx); -} - -#include <gbp/gbp.api.c> -static clib_error_t * -gbp_init (vlib_main_t * vm) -{ - gbp_main_t *gbpm = &gbp_main; - - gbpm->gbp_acl_user_id = ~0; - - /* Ask for a correctly-sized block of API message decode slots */ - msg_id_base = setup_message_id_table (); - - return (NULL); -} - -VLIB_API_INIT_FUNCTION (gbp_init); - -/* *INDENT-OFF* */ -VLIB_PLUGIN_REGISTER () = { - .version = VPP_BUILD_VER, - .description = "Group Based Policy (GBP)", -}; -/* *INDENT-ON* */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_bridge_domain.c b/src/plugins/gbp/gbp_bridge_domain.c deleted file mode 100644 index 279169abb1d..00000000000 --- a/src/plugins/gbp/gbp_bridge_domain.c +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp_bridge_domain.h> -#include <plugins/gbp/gbp_route_domain.h> -#include <plugins/gbp/gbp_endpoint.h> -#include <plugins/gbp/gbp_learn.h> -#include <plugins/gbp/gbp_itf.h> - -#include <vnet/dpo/dvr_dpo.h> -#include <vnet/fib/fib_table.h> -#include <vnet/l2/l2_input.h> -#include <vnet/l2/feat_bitmap.h> -#include <vnet/l2/l2_bvi.h> -#include <vnet/l2/l2_fib.h> - -/** - * Pool of GBP bridge_domains - */ -gbp_bridge_domain_t *gbp_bridge_domain_pool; - -/** - * DB of bridge_domains - */ -gbp_bridge_domain_db_t gbp_bridge_domain_db; - -/** - * Map of BD index to contract scope - */ -gbp_scope_t *gbp_scope_by_bd_index; - -/** - * logger - */ -vlib_log_class_t gb_logger; - -#define GBP_BD_DBG(...) \ - vlib_log_debug (gb_logger, __VA_ARGS__); - -index_t -gbp_bridge_domain_index (const gbp_bridge_domain_t * gbd) -{ - return (gbd - gbp_bridge_domain_pool); -} - -static void -gbp_bridge_domain_lock (index_t i) -{ - gbp_bridge_domain_t *gb; - - gb = gbp_bridge_domain_get (i); - gb->gb_locks++; -} - -u32 -gbp_bridge_domain_get_bd_id (index_t gbdi) -{ - gbp_bridge_domain_t *gb; - - gb = gbp_bridge_domain_get (gbdi); - - return (gb->gb_bd_id); -} - -static index_t -gbp_bridge_domain_find (u32 bd_id) -{ - uword *p; - - p = hash_get (gbp_bridge_domain_db.gbd_by_bd_id, bd_id); - - if (NULL != p) - return p[0]; - - return (INDEX_INVALID); -} - -index_t -gbp_bridge_domain_find_and_lock (u32 bd_id) -{ - uword *p; - - p = hash_get (gbp_bridge_domain_db.gbd_by_bd_id, bd_id); - - if (NULL != p) - { - gbp_bridge_domain_lock (p[0]); - return p[0]; - } - return (INDEX_INVALID); -} - -static void -gbp_bridge_domain_db_add (gbp_bridge_domain_t * gb) -{ - index_t gbi = gb - gbp_bridge_domain_pool; - - hash_set (gbp_bridge_domain_db.gbd_by_bd_id, gb->gb_bd_id, gbi); - vec_validate_init_empty (gbp_bridge_domain_db.gbd_by_bd_index, - gb->gb_bd_index, INDEX_INVALID); - gbp_bridge_domain_db.gbd_by_bd_index[gb->gb_bd_index] = gbi; -} - -static void -gbp_bridge_domain_db_remove (gbp_bridge_domain_t * gb) -{ - hash_unset (gbp_bridge_domain_db.gbd_by_bd_id, gb->gb_bd_id); - gbp_bridge_domain_db.gbd_by_bd_index[gb->gb_bd_index] = INDEX_INVALID; -} - -u8 * -format_gbp_bridge_domain_flags (u8 * s, va_list * args) -{ - gbp_bridge_domain_flags_t gf = va_arg (*args, gbp_bridge_domain_flags_t); - - if (gf) - { - if (gf & GBP_BD_FLAG_DO_NOT_LEARN) - s = format (s, "do-not-learn "); - if (gf & GBP_BD_FLAG_UU_FWD_DROP) - s = format (s, "uu-fwd-drop "); - if (gf & GBP_BD_FLAG_MCAST_DROP) - s = format (s, "mcast-drop "); - if (gf & GBP_BD_FLAG_UCAST_ARP) - s = format (s, "ucast-arp "); - } - else - { - s = format (s, "none"); - } - return (s); -} - -static u8 * -format_gbp_bridge_domain_ptr (u8 * s, va_list * args) -{ - gbp_bridge_domain_t *gb = va_arg (*args, gbp_bridge_domain_t *); - vnet_main_t *vnm = vnet_get_main (); - - if (NULL != gb) - s = - format (s, - "[%d] bd:[%d,%d], bvi:%U uu-flood:%U bm-flood:%U flags:%U locks:%d", - gb - gbp_bridge_domain_pool, gb->gb_bd_id, gb->gb_bd_index, - format_vnet_sw_if_index_name, vnm, gb->gb_bvi_sw_if_index, - format_vnet_sw_if_index_name, vnm, gb->gb_uu_fwd_sw_if_index, - format_gbp_itf_hdl, gb->gb_bm_flood_itf, - format_gbp_bridge_domain_flags, gb->gb_flags, gb->gb_locks); - else - s = format (s, "NULL"); - - return (s); -} - -u8 * -format_gbp_bridge_domain (u8 * s, va_list * args) -{ - index_t gbi = va_arg (*args, index_t); - - s = - format (s, "%U", format_gbp_bridge_domain_ptr, - gbp_bridge_domain_get (gbi)); - - return (s); -} - -int -gbp_bridge_domain_add_and_lock (u32 bd_id, - u32 rd_id, - gbp_bridge_domain_flags_t flags, - u32 bvi_sw_if_index, - u32 uu_fwd_sw_if_index, - u32 bm_flood_sw_if_index) -{ - gbp_bridge_domain_t *gb; - index_t gbi; - - gbi = gbp_bridge_domain_find (bd_id); - - if (INDEX_INVALID == gbi) - { - gbp_route_domain_t *gr; - u32 bd_index; - - bd_index = bd_find_index (&bd_main, bd_id); - - if (~0 == bd_index) - return (VNET_API_ERROR_BD_NOT_MODIFIABLE); - - bd_flags_t bd_flags = L2_NONE; - if (flags & GBP_BD_FLAG_UU_FWD_DROP) - bd_flags |= L2_UU_FLOOD; - if (flags & GBP_BD_FLAG_MCAST_DROP) - bd_flags |= L2_FLOOD; - - pool_get (gbp_bridge_domain_pool, gb); - memset (gb, 0, sizeof (*gb)); - - gbi = gb - gbp_bridge_domain_pool; - gb->gb_bd_id = bd_id; - gb->gb_bd_index = bd_index; - gb->gb_uu_fwd_sw_if_index = uu_fwd_sw_if_index; - gb->gb_bvi_sw_if_index = bvi_sw_if_index; - gbp_itf_hdl_reset (&gb->gb_bm_flood_itf); - gb->gb_locks = 1; - gb->gb_flags = flags; - gb->gb_rdi = gbp_route_domain_find_and_lock (rd_id); - - /* - * set the scope from the BD's RD's scope - */ - gr = gbp_route_domain_get (gb->gb_rdi); - vec_validate (gbp_scope_by_bd_index, gb->gb_bd_index); - gbp_scope_by_bd_index[gb->gb_bd_index] = gr->grd_scope; - - /* - * Set the BVI and uu-flood interfaces into the BD - */ - gbp_bridge_domain_itf_add (gbi, gb->gb_bvi_sw_if_index, - L2_BD_PORT_TYPE_BVI); - - if ((!(flags & GBP_BD_FLAG_UU_FWD_DROP) || - (flags & GBP_BD_FLAG_UCAST_ARP)) && - ~0 != gb->gb_uu_fwd_sw_if_index) - gbp_bridge_domain_itf_add (gbi, gb->gb_uu_fwd_sw_if_index, - L2_BD_PORT_TYPE_UU_FWD); - - if (!(flags & GBP_BD_FLAG_MCAST_DROP) && ~0 != bm_flood_sw_if_index) - { - gb->gb_bm_flood_itf = - gbp_itf_l2_add_and_lock (bm_flood_sw_if_index, gbi); - gbp_itf_l2_set_input_feature (gb->gb_bm_flood_itf, - L2INPUT_FEAT_GBP_LEARN); - } - - /* - * unset any flag(s) set above - */ - bd_set_flags (vlib_get_main (), bd_index, bd_flags, 0); - - if (flags & GBP_BD_FLAG_UCAST_ARP) - { - bd_flags = L2_ARP_UFWD; - bd_set_flags (vlib_get_main (), bd_index, bd_flags, 1); - } - - /* - * Add the BVI's MAC to the L2FIB - */ - l2fib_add_entry (vnet_sw_interface_get_hw_address - (vnet_get_main (), gb->gb_bvi_sw_if_index), - gb->gb_bd_index, gb->gb_bvi_sw_if_index, - (L2FIB_ENTRY_RESULT_FLAG_STATIC | - L2FIB_ENTRY_RESULT_FLAG_BVI)); - - gbp_bridge_domain_db_add (gb); - } - else - { - gb = gbp_bridge_domain_get (gbi); - gb->gb_locks++; - } - - GBP_BD_DBG ("add: %U", format_gbp_bridge_domain_ptr, gb); - - return (0); -} - -void -gbp_bridge_domain_itf_add (index_t gbdi, - u32 sw_if_index, l2_bd_port_type_t type) -{ - gbp_bridge_domain_t *gb; - - gb = gbp_bridge_domain_get (gbdi); - - set_int_l2_mode (vlib_get_main (), vnet_get_main (), MODE_L2_BRIDGE, - sw_if_index, gb->gb_bd_index, type, 0, 0); - /* - * adding an interface to the bridge enables learning on the - * interface. Disable learning on the interface by default for gbp - * interfaces - */ - l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_LEARN, 0); -} - -void -gbp_bridge_domain_itf_del (index_t gbdi, - u32 sw_if_index, l2_bd_port_type_t type) -{ - gbp_bridge_domain_t *gb; - - gb = gbp_bridge_domain_get (gbdi); - - set_int_l2_mode (vlib_get_main (), vnet_get_main (), MODE_L3, sw_if_index, - gb->gb_bd_index, type, 0, 0); -} - -void -gbp_bridge_domain_unlock (index_t gbdi) -{ - gbp_bridge_domain_t *gb; - - gb = gbp_bridge_domain_get (gbdi); - - gb->gb_locks--; - - if (0 == gb->gb_locks) - { - GBP_BD_DBG ("destroy: %U", format_gbp_bridge_domain_ptr, gb); - - l2fib_del_entry (vnet_sw_interface_get_hw_address - (vnet_get_main (), gb->gb_bvi_sw_if_index), - gb->gb_bd_index, gb->gb_bvi_sw_if_index); - - gbp_bridge_domain_itf_del (gbdi, gb->gb_bvi_sw_if_index, - L2_BD_PORT_TYPE_BVI); - if (~0 != gb->gb_uu_fwd_sw_if_index) - gbp_bridge_domain_itf_del (gbdi, gb->gb_uu_fwd_sw_if_index, - L2_BD_PORT_TYPE_UU_FWD); - gbp_itf_unlock (&gb->gb_bm_flood_itf); - - gbp_bridge_domain_db_remove (gb); - gbp_route_domain_unlock (gb->gb_rdi); - - pool_put (gbp_bridge_domain_pool, gb); - } -} - -int -gbp_bridge_domain_delete (u32 bd_id) -{ - index_t gbi; - - GBP_BD_DBG ("del: %d", bd_id); - gbi = gbp_bridge_domain_find (bd_id); - - if (INDEX_INVALID != gbi) - { - GBP_BD_DBG ("del: %U", format_gbp_bridge_domain, gbi); - gbp_bridge_domain_unlock (gbi); - - return (0); - } - - return (VNET_API_ERROR_NO_SUCH_ENTRY); -} - -void -gbp_bridge_domain_walk (gbp_bridge_domain_cb_t cb, void *ctx) -{ - gbp_bridge_domain_t *gbpe; - - /* *INDENT-OFF* */ - pool_foreach (gbpe, gbp_bridge_domain_pool) - { - if (!cb(gbpe, ctx)) - break; - } - /* *INDENT-ON* */ -} - -static clib_error_t * -gbp_bridge_domain_cli (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - vnet_main_t *vnm = vnet_get_main (); - gbp_bridge_domain_flags_t flags; - u32 bm_flood_sw_if_index = ~0; - u32 uu_fwd_sw_if_index = ~0; - u32 bd_id = ~0, rd_id = ~0; - u32 bvi_sw_if_index = ~0; - u8 add = 1; - - flags = GBP_BD_FLAG_NONE; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "bvi %U", unformat_vnet_sw_interface, - vnm, &bvi_sw_if_index)) - ; - else if (unformat (input, "uu-fwd %U", unformat_vnet_sw_interface, - vnm, &uu_fwd_sw_if_index)) - ; - else if (unformat (input, "bm-flood %U", unformat_vnet_sw_interface, - vnm, &bm_flood_sw_if_index)) - ; - else if (unformat (input, "add")) - add = 1; - else if (unformat (input, "del")) - add = 0; - else if (unformat (input, "flags %d", &flags)) - ; - else if (unformat (input, "bd %d", &bd_id)) - ; - else if (unformat (input, "rd %d", &rd_id)) - ; - else - break; - } - - if (~0 == bd_id) - return clib_error_return (0, "BD-ID must be specified"); - if (~0 == rd_id) - return clib_error_return (0, "RD-ID must be specified"); - - if (add) - { - if (~0 == bvi_sw_if_index) - return clib_error_return (0, "interface must be specified"); - - gbp_bridge_domain_add_and_lock (bd_id, rd_id, - flags, - bvi_sw_if_index, - uu_fwd_sw_if_index, - bm_flood_sw_if_index); - } - else - gbp_bridge_domain_delete (bd_id); - - return (NULL); -} - -/*? - * Configure a GBP bridge-domain - * - * @cliexpar - * @cliexstart{gbp bridge-domain [del] bd <ID> bvi <interface> [uu-fwd <interface>] [bm-flood <interface>] [flags <flags>]} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_bridge_domain_cli_node, static) = { - .path = "gbp bridge-domain", - .short_help = "gbp bridge-domain [del] bd <ID> bvi <interface> [uu-fwd <interface>] [bm-flood <interface>] [flags <flags>]", - .function = gbp_bridge_domain_cli, -}; - -static int -gbp_bridge_domain_show_one (gbp_bridge_domain_t *gb, void *ctx) -{ - vlib_main_t *vm; - - vm = ctx; - vlib_cli_output (vm, " %U", format_gbp_bridge_domain_ptr, gb); - - return (1); -} - -static clib_error_t * -gbp_bridge_domain_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - vlib_cli_output (vm, "Bridge-Domains:"); - gbp_bridge_domain_walk (gbp_bridge_domain_show_one, vm); - - return (NULL); -} - - -/*? - * Show Group Based Policy Bridge_Domains and derived information - * - * @cliexpar - * @cliexstart{show gbp bridge_domain} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_bridge_domain_show_node, static) = { - .path = "show gbp bridge-domain", - .short_help = "show gbp bridge-domain\n", - .function = gbp_bridge_domain_show, -}; -/* *INDENT-ON* */ - -static clib_error_t * -gbp_bridge_domain_init (vlib_main_t * vm) -{ - gb_logger = vlib_log_register_class ("gbp", "bd"); - - return (NULL); -} - -VLIB_INIT_FUNCTION (gbp_bridge_domain_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_bridge_domain.h b/src/plugins/gbp/gbp_bridge_domain.h deleted file mode 100644 index 0449240083c..00000000000 --- a/src/plugins/gbp/gbp_bridge_domain.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_BRIDGE_DOMAIN_H__ -#define __GBP_BRIDGE_DOMAIN_H__ - -#include <plugins/gbp/gbp_types.h> -#include <plugins/gbp/gbp_itf.h> - -#include <vnet/fib/fib_types.h> -#include <vnet/l2/l2_bd.h> - -/** - * Bridge Domain Flags - */ -typedef enum gbp_bridge_domain_flags_t_ -{ - GBP_BD_FLAG_NONE = 0, - GBP_BD_FLAG_DO_NOT_LEARN = (1 << 0), - GBP_BD_FLAG_UU_FWD_DROP = (1 << 1), - GBP_BD_FLAG_MCAST_DROP = (1 << 2), - GBP_BD_FLAG_UCAST_ARP = (1 << 3), -} gbp_bridge_domain_flags_t; - -/** - * A bridge Domain Representation. - * This is a standard bridge-domain plus all the attributes it must - * have to supprt the GBP model. - */ -typedef struct gbp_bridge_domain_t_ -{ - /** - * Bridge-domain ID - */ - u32 gb_bd_id; - u32 gb_bd_index; - - /** - * Index of the Route-domain this BD is associated with. This is used as the - * 'scope' of the packets for contract matching. - */ - u32 gb_rdi; - - /** - * Flags conttrolling behaviour - */ - gbp_bridge_domain_flags_t gb_flags; - - /** - * The BD's BVI interface (obligatory) - */ - u32 gb_bvi_sw_if_index; - - /** - * The BD's MAC spine-proxy interface (optional) - */ - u32 gb_uu_fwd_sw_if_index; - - /** - * The BD's interface to sned Broadcast and multicast packets - */ - gbp_itf_hdl_t gb_bm_flood_itf; - - /** - * The index of the BD's VNI interface on which packets from - * unkown endpoints arrive - */ - u32 gb_vni; - - /** - * locks/references to the BD so it does not get deleted (from the API) - * whilst it is still being used - */ - u32 gb_locks; -} gbp_bridge_domain_t; - -extern void gbp_bridge_domain_itf_add (index_t gbdi, - u32 sw_if_index, - l2_bd_port_type_t type); -extern void gbp_bridge_domain_itf_del (index_t gbdi, - u32 sw_if_index, - l2_bd_port_type_t type); - -extern int gbp_bridge_domain_add_and_lock (u32 bd_id, - u32 rd_id, - gbp_bridge_domain_flags_t flags, - u32 bvi_sw_if_index, - u32 uu_fwd_sw_if_index, - u32 bm_flood_sw_if_index); - -extern void gbp_bridge_domain_unlock (index_t gbi); -extern index_t gbp_bridge_domain_find_and_lock (u32 bd_id); -extern int gbp_bridge_domain_delete (u32 bd_id); -extern index_t gbp_bridge_domain_index (const gbp_bridge_domain_t *); -extern u32 gbp_bridge_domain_get_bd_id (index_t gbdi); - -typedef int (*gbp_bridge_domain_cb_t) (gbp_bridge_domain_t * gb, void *ctx); -extern void gbp_bridge_domain_walk (gbp_bridge_domain_cb_t bgpe, void *ctx); - -extern u8 *format_gbp_bridge_domain (u8 * s, va_list * args); -extern u8 *format_gbp_bridge_domain_flags (u8 * s, va_list * args); - -/** - * DB of bridge_domains - */ -typedef struct gbp_bridge_domain_db_t -{ - uword *gbd_by_bd_id; - index_t *gbd_by_bd_index; -} gbp_bridge_domain_db_t; - -extern gbp_bridge_domain_db_t gbp_bridge_domain_db; -extern gbp_bridge_domain_t *gbp_bridge_domain_pool; - -always_inline gbp_bridge_domain_t * -gbp_bridge_domain_get (index_t i) -{ - return (pool_elt_at_index (gbp_bridge_domain_pool, i)); -} - -always_inline gbp_bridge_domain_t * -gbp_bridge_domain_get_by_bd_index (u32 bd_index) -{ - return (gbp_bridge_domain_get - (gbp_bridge_domain_db.gbd_by_bd_index[bd_index])); -} - -extern gbp_scope_t *gbp_scope_by_bd_index; - -always_inline gbp_scope_t -gbp_bridge_domain_get_scope (u32 bd_index) -{ - return (gbp_scope_by_bd_index[bd_index]); -} - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_classify.c b/src/plugins/gbp/gbp_classify.c deleted file mode 100644 index 255db252871..00000000000 --- a/src/plugins/gbp/gbp_classify.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * gbp.h : Group Based Policy - * - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp.h> -#include <plugins/gbp/gbp_classify.h> -#include <vnet/l2/l2_input.h> - -gbp_src_classify_main_t gbp_src_classify_main; - -static clib_error_t * -gbp_src_classify_init (vlib_main_t * vm) -{ - gbp_src_classify_main_t *em = &gbp_src_classify_main; - - vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "gbp-src-classify"); - - /* Initialize the feature next-node indexes */ - feat_bitmap_init_next_nodes (vm, - node->index, - L2INPUT_N_FEAT, - l2input_get_feat_names (), - em->l2_input_feat_next[GBP_SRC_CLASSIFY_NULL]); - - node = vlib_get_node_by_name (vm, (u8 *) "gbp-null-classify"); - feat_bitmap_init_next_nodes (vm, - node->index, - L2INPUT_N_FEAT, - l2input_get_feat_names (), - em->l2_input_feat_next[GBP_SRC_CLASSIFY_PORT]); - - node = vlib_get_node_by_name (vm, (u8 *) "l2-gbp-lpm-classify"); - feat_bitmap_init_next_nodes (vm, - node->index, - L2INPUT_N_FEAT, - l2input_get_feat_names (), - em->l2_input_feat_next[GBP_SRC_CLASSIFY_LPM]); - - node = vlib_get_node_by_name (vm, (u8 *) "l2-gbp-lpm-anon-classify"); - feat_bitmap_init_next_nodes (vm, - node->index, - L2INPUT_N_FEAT, - l2input_get_feat_names (), - em->l2_input_feat_next - [GBP_SRC_CLASSIFY_LPM_ANON]); - - return 0; -} - -VLIB_INIT_FUNCTION (gbp_src_classify_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_classify.h b/src/plugins/gbp/gbp_classify.h deleted file mode 100644 index ca7db94a2c0..00000000000 --- a/src/plugins/gbp/gbp_classify.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * gbp.h : Group Based Policy - * - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_CLASSIFY_H__ -#define __GBP_CLASSIFY_H__ - -#include <plugins/gbp/gbp.h> -#include <vnet/ethernet/arp_packet.h> - -typedef enum gbp_src_classify_type_t_ -{ - GBP_SRC_CLASSIFY_NULL, - GBP_SRC_CLASSIFY_PORT, - GBP_SRC_CLASSIFY_LPM, - GBP_SRC_CLASSIFY_LPM_ANON, - GBP_SRC_N_CLASSIFY -#define GBP_SRC_N_CLASSIFY GBP_SRC_N_CLASSIFY -} gbp_src_classify_type_t; - -/** - * Grouping of global data for the GBP source EPG classification feature - */ -typedef struct gbp_src_classify_main_t_ -{ - /** - * Next nodes for L2 output features - */ - u32 l2_input_feat_next[GBP_SRC_N_CLASSIFY][32]; -} gbp_src_classify_main_t; - -extern gbp_src_classify_main_t gbp_src_classify_main; - -enum gbp_classify_get_ip_way -{ - GBP_CLASSIFY_GET_IP_SRC = 0, - GBP_CLASSIFY_GET_IP_DST = 1 -}; - -static_always_inline dpo_proto_t -gbp_classify_get_ip_address (const ethernet_header_t * eh0, - const ip4_address_t ** ip4, - const ip6_address_t ** ip6, - const enum gbp_classify_get_ip_way way) -{ - u16 etype = clib_net_to_host_u16 (eh0->type); - const void *l3h0 = eh0 + 1; - - if (ETHERNET_TYPE_VLAN == etype) - { - const ethernet_vlan_header_t *vh0 = - (ethernet_vlan_header_t *) (eh0 + 1); - etype = clib_net_to_host_u16 (vh0->type); - l3h0 = vh0 + 1; - } - - switch (etype) - { - case ETHERNET_TYPE_IP4: - *ip4 = &(&((const ip4_header_t *) l3h0)->src_address)[way]; - return DPO_PROTO_IP4; - case ETHERNET_TYPE_IP6: - *ip6 = &(&((const ip6_header_t *) l3h0)->src_address)[way]; - return DPO_PROTO_IP6; - case ETHERNET_TYPE_ARP: - *ip4 = &((ethernet_arp_header_t *) l3h0)->ip4_over_ethernet[way].ip4; - return DPO_PROTO_IP4; - } - - return DPO_PROTO_NONE; -} - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_classify_node.c b/src/plugins/gbp/gbp_classify_node.c deleted file mode 100644 index a2058a21284..00000000000 --- a/src/plugins/gbp/gbp_classify_node.c +++ /dev/null @@ -1,628 +0,0 @@ -/* - * gbp.h : Group Based Policy - * - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp.h> -#include <plugins/gbp/gbp_classify.h> -#include <plugins/gbp/gbp_policy_dpo.h> -#include <plugins/gbp/gbp_ext_itf.h> -#include <vnet/fib/ip4_fib.h> -#include <vnet/fib/ip6_fib.h> -#include <vnet/dpo/load_balance.h> -#include <vnet/l2/l2_input.h> -#include <vnet/l2/feat_bitmap.h> -#include <vnet/fib/fib_table.h> -#include <vnet/vxlan-gbp/vxlan_gbp_packet.h> -#include <vnet/ethernet/arp_packet.h> - -/** - * per-packet trace data - */ -typedef struct gbp_classify_trace_t_ -{ - /* per-pkt trace data */ - sclass_t sclass; -} gbp_classify_trace_t; - -/* - * determine the SRC EPG form the input port - */ -always_inline uword -gbp_classify_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, - gbp_src_classify_type_t type, dpo_proto_t dproto) -{ - gbp_src_classify_main_t *gscm = &gbp_src_classify_main; - u32 n_left_from, *from, *to_next; - u32 next_index; - - next_index = 0; - n_left_from = frame->n_vectors; - from = vlib_frame_vector_args (frame); - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 next0, bi0, sw_if_index0; - const gbp_endpoint_t *ge0; - vlib_buffer_t *b0; - sclass_t sclass0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - vnet_buffer2 (b0)->gbp.flags = VXLAN_GBP_GPFLAGS_NONE; - - if (GBP_SRC_CLASSIFY_NULL == type) - { - sclass0 = SCLASS_INVALID; - next0 = - vnet_l2_feature_next (b0, gscm->l2_input_feat_next[type], - L2INPUT_FEAT_GBP_NULL_CLASSIFY); - } - else - { - if (DPO_PROTO_ETHERNET == dproto) - { - const ethernet_header_t *h0; - - h0 = vlib_buffer_get_current (b0); - next0 = - vnet_l2_feature_next (b0, gscm->l2_input_feat_next[type], - L2INPUT_FEAT_GBP_SRC_CLASSIFY); - ge0 = gbp_endpoint_find_mac (h0->src_address, - vnet_buffer (b0)->l2.bd_index); - } - else if (DPO_PROTO_IP4 == dproto) - { - const ip4_header_t *h0; - - h0 = vlib_buffer_get_current (b0); - - ge0 = gbp_endpoint_find_ip4 - (&h0->src_address, - fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, - sw_if_index0)); - - - /* - * Go straight to looukp, do not pass go, do not collect $200 - */ - next0 = 0; - } - else if (DPO_PROTO_IP6 == dproto) - { - const ip6_header_t *h0; - - h0 = vlib_buffer_get_current (b0); - - ge0 = gbp_endpoint_find_ip6 - (&h0->src_address, - fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, - sw_if_index0)); - - - /* - * Go straight to lookup, do not pass go, do not collect $200 - */ - next0 = 0; - } - else - { - ge0 = NULL; - next0 = 0; - ASSERT (0); - } - - if (PREDICT_TRUE (NULL != ge0)) - sclass0 = ge0->ge_fwd.gef_sclass; - else - sclass0 = SCLASS_INVALID; - } - - vnet_buffer2 (b0)->gbp.sclass = sclass0; - - if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_IS_TRACED))) - { - gbp_classify_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->sclass = sclass0; - } - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - -VLIB_NODE_FN (gbp_src_classify_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_classify_inline (vm, node, frame, - GBP_SRC_CLASSIFY_PORT, DPO_PROTO_ETHERNET)); -} - -VLIB_NODE_FN (gbp_null_classify_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_classify_inline (vm, node, frame, - GBP_SRC_CLASSIFY_NULL, DPO_PROTO_ETHERNET)); -} - -VLIB_NODE_FN (gbp_ip4_src_classify_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_classify_inline (vm, node, frame, - GBP_SRC_CLASSIFY_PORT, DPO_PROTO_IP4)); -} - -VLIB_NODE_FN (gbp_ip6_src_classify_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_classify_inline (vm, node, frame, - GBP_SRC_CLASSIFY_PORT, DPO_PROTO_IP6)); -} - - -/* packet trace format function */ -static u8 * -format_gbp_classify_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - gbp_classify_trace_t *t = va_arg (*args, gbp_classify_trace_t *); - - s = format (s, "sclass:%d", t->sclass); - - return s; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (gbp_null_classify_node) = { - .name = "gbp-null-classify", - .vector_size = sizeof (u32), - .format_trace = format_gbp_classify_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = 0, - .n_next_nodes = 0, -}; - -VLIB_REGISTER_NODE (gbp_src_classify_node) = { - .name = "gbp-src-classify", - .vector_size = sizeof (u32), - .format_trace = format_gbp_classify_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = 0, - .n_next_nodes = 0, -}; - -VLIB_REGISTER_NODE (gbp_ip4_src_classify_node) = { - .name = "ip4-gbp-src-classify", - .vector_size = sizeof (u32), - .format_trace = format_gbp_classify_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = 0, - .n_next_nodes = 1, - .next_nodes = { - [0] = "ip4-lookup" - }, -}; - -VLIB_REGISTER_NODE (gbp_ip6_src_classify_node) = { - .name = "ip6-gbp-src-classify", - .vector_size = sizeof (u32), - .format_trace = format_gbp_classify_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = 0, - .n_next_nodes = 1, - .next_nodes = { - [0] = "ip6-lookup" - }, -}; - -VNET_FEATURE_INIT (gbp_ip4_src_classify_feat_node, static) = -{ - .arc_name = "ip4-unicast", - .node_name = "ip4-gbp-src-classify", - .runs_before = VNET_FEATURES ("nat44-out2in"), -}; -VNET_FEATURE_INIT (gbp_ip6_src_classify_feat_node, static) = -{ - .arc_name = "ip6-unicast", - .node_name = "ip6-gbp-src-classify", - .runs_before = VNET_FEATURES ("nat66-out2in"), -}; - -/* *INDENT-ON* */ - -typedef enum gbp_lpm_classify_next_t_ -{ - GPB_LPM_CLASSIFY_DROP, -} gbp_lpm_classify_next_t; - -/** - * per-packet trace data - */ -typedef struct gbp_lpm_classify_trace_t_ -{ - sclass_t sclass; - index_t lbi; - ip46_address_t src; -} gbp_lpm_classify_trace_t; - -/* packet trace format function */ -static u8 * -format_gbp_lpm_classify_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - gbp_lpm_classify_trace_t *t = va_arg (*args, gbp_lpm_classify_trace_t *); - - s = format (s, "sclass:%d lb:%d src:%U", - t->sclass, t->lbi, format_ip46_address, &t->src, IP46_TYPE_ANY); - - return s; -} - -enum gbp_lpm_type -{ - GBP_LPM_RECIRC, - GBP_LPM_EPG, - GBP_LPM_ANON -}; - -/* - * Determine the SRC EPG from a LPM - */ -always_inline uword -gbp_lpm_classify_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, - const dpo_proto_t dproto, - const enum gbp_lpm_type type) -{ - gbp_src_classify_main_t *gscm = &gbp_src_classify_main; - u32 n_left_from, *from, *to_next; - u32 next_index; - - next_index = 0; - n_left_from = frame->n_vectors; - from = vlib_frame_vector_args (frame); - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0, sw_if_index0, fib_index0, lbi0; - const gbp_endpoint_t *ge0, *ge_lpm0; - gbp_lpm_classify_next_t next0; - const ethernet_header_t *eh0; - const gbp_policy_dpo_t *gpd0; - const ip4_address_t *ip4_0; - const ip6_address_t *ip6_0; - const gbp_recirc_t *gr0; - vlib_buffer_t *b0; - sclass_t sclass0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - ip4_0 = NULL; - ip6_0 = NULL; - next0 = GPB_LPM_CLASSIFY_DROP; - - lbi0 = ~0; - eh0 = NULL; - b0 = vlib_get_buffer (vm, bi0); - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - vnet_buffer2 (b0)->gbp.flags = VXLAN_GBP_GPFLAGS_NONE; - - if (DPO_PROTO_IP4 == dproto) - ip4_0 = - &((ip4_header_t *) vlib_buffer_get_current (b0))->src_address; - else if (DPO_PROTO_IP6 == dproto) - ip6_0 = - &((ip6_header_t *) vlib_buffer_get_current (b0))->src_address; - else if (DPO_PROTO_ETHERNET == dproto) - { - eh0 = vlib_buffer_get_current (b0); - gbp_classify_get_ip_address (eh0, &ip4_0, &ip6_0, - GBP_CLASSIFY_GET_IP_SRC); - } - - if (GBP_LPM_RECIRC == type) - { - gr0 = gbp_recirc_get (sw_if_index0); - fib_index0 = gr0->gr_fib_index[dproto]; - ge0 = NULL; - - vnet_feature_next (&next0, b0); - } - else - { - if (NULL == eh0) - { - /* packet should be l2 */ - sclass0 = SCLASS_INVALID; - goto trace; - } - - if (GBP_LPM_ANON == type) - { - /* - * anonymous LPM classification: only honour LPM as no EP - * were programmed - */ - gbp_ext_itf_t *gei = gbp_ext_itf_get (sw_if_index0); - if (ip4_0) - fib_index0 = gei->gx_fib_index[DPO_PROTO_IP4]; - else if (ip6_0) - fib_index0 = gei->gx_fib_index[DPO_PROTO_IP6]; - else - { - /* not IP so no LPM classify possible */ - sclass0 = SCLASS_INVALID; - next0 = GPB_LPM_CLASSIFY_DROP; - goto trace; - } - next0 = vnet_l2_feature_next - (b0, gscm->l2_input_feat_next[GBP_SRC_CLASSIFY_LPM_ANON], - L2INPUT_FEAT_GBP_LPM_ANON_CLASSIFY); - } - else - { - /* - * not an anonymous LPM classification: check it comes from - * an EP, and use EP RD info - */ - ge0 = gbp_endpoint_find_mac (eh0->src_address, - vnet_buffer (b0)->l2.bd_index); - - if (NULL == ge0) - { - /* packet must have come from an EP's mac */ - sclass0 = SCLASS_INVALID; - goto trace; - } - - fib_index0 = ge0->ge_fwd.gef_fib_index; - - if (~0 == fib_index0) - { - sclass0 = SCLASS_INVALID; - goto trace; - } - - if (ip4_0) - { - ge_lpm0 = gbp_endpoint_find_ip4 (ip4_0, fib_index0); - } - else if (ip6_0) - { - ge_lpm0 = gbp_endpoint_find_ip6 (ip6_0, fib_index0); - } - else - { - ge_lpm0 = NULL; - } - - next0 = vnet_l2_feature_next - (b0, gscm->l2_input_feat_next[GBP_SRC_CLASSIFY_LPM], - L2INPUT_FEAT_GBP_LPM_CLASSIFY); - - /* - * if we found the EP by IP lookup, it must be from the EP - * not a network behind it - */ - if (NULL != ge_lpm0) - { - if (PREDICT_FALSE (ge0 != ge_lpm0)) - { - /* an EP spoofing another EP */ - sclass0 = SCLASS_INVALID; - next0 = GPB_LPM_CLASSIFY_DROP; - } - else - { - sclass0 = ge0->ge_fwd.gef_sclass; - } - goto trace; - } - } - } - - gpd0 = gbp_classify_get_gpd (ip4_0, ip6_0, fib_index0); - if (0 == gpd0) - { - /* could not classify => drop */ - sclass0 = SCLASS_INVALID; - next0 = GPB_LPM_CLASSIFY_DROP; - goto trace; - } - - sclass0 = gpd0->gpd_sclass; - - /* all packets from an external network should not be learned by the - * reciever. so set the Do-not-learn bit here */ - vnet_buffer2 (b0)->gbp.flags = VXLAN_GBP_GPFLAGS_D; - - trace: - vnet_buffer2 (b0)->gbp.sclass = sclass0; - - if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_IS_TRACED))) - { - gbp_lpm_classify_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->sclass = sclass0; - t->lbi = lbi0; - if (ip4_0) - t->src.ip4 = *ip4_0; - if (ip6_0) - t->src.ip6 = *ip6_0; - } - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - -VLIB_NODE_FN (gbp_ip4_lpm_classify_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_lpm_classify_inline - (vm, node, frame, DPO_PROTO_IP4, GBP_LPM_RECIRC)); -} - -VLIB_NODE_FN (gbp_ip6_lpm_classify_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_lpm_classify_inline - (vm, node, frame, DPO_PROTO_IP6, GBP_LPM_RECIRC)); -} - -VLIB_NODE_FN (gbp_l2_lpm_classify_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_lpm_classify_inline - (vm, node, frame, DPO_PROTO_ETHERNET, GBP_LPM_EPG)); -} - -VLIB_NODE_FN (gbp_l2_lpm_anon_classify_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_lpm_classify_inline - (vm, node, frame, DPO_PROTO_ETHERNET, GBP_LPM_ANON)); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (gbp_ip4_lpm_classify_node) = { - .name = "ip4-gbp-lpm-classify", - .vector_size = sizeof (u32), - .format_trace = format_gbp_lpm_classify_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = 0, - .n_next_nodes = 1, - .next_nodes = { - [GPB_LPM_CLASSIFY_DROP] = "ip4-drop" - }, -}; - -VLIB_REGISTER_NODE (gbp_ip6_lpm_classify_node) = { - .name = "ip6-gbp-lpm-classify", - .vector_size = sizeof (u32), - .format_trace = format_gbp_lpm_classify_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = 0, - .n_next_nodes = 1, - .next_nodes = { - [GPB_LPM_CLASSIFY_DROP] = "ip6-drop" - }, -}; - -VLIB_REGISTER_NODE (gbp_l2_lpm_classify_node) = { - .name = "l2-gbp-lpm-classify", - .vector_size = sizeof (u32), - .format_trace = format_gbp_lpm_classify_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = 0, - .n_next_nodes = 1, - .next_nodes = { - [GPB_LPM_CLASSIFY_DROP] = "error-drop" - }, -}; - -VLIB_REGISTER_NODE (gbp_l2_lpm_anon_classify_node) = { - .name = "l2-gbp-lpm-anon-classify", - .vector_size = sizeof (u32), - .format_trace = format_gbp_lpm_classify_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = 0, - .n_next_nodes = 1, - .next_nodes = { - [GPB_LPM_CLASSIFY_DROP] = "error-drop" - }, -}; - -VNET_FEATURE_INIT (gbp_ip4_lpm_classify_feat_node, static) = -{ - .arc_name = "ip4-unicast", - .node_name = "ip4-gbp-lpm-classify", - .runs_before = VNET_FEATURES ("nat44-out2in"), -}; -VNET_FEATURE_INIT (gbp_ip6_lpm_classify_feat_node, static) = -{ - .arc_name = "ip6-unicast", - .node_name = "ip6-gbp-lpm-classify", - .runs_before = VNET_FEATURES ("nat66-out2in"), -}; - -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_contract.c b/src/plugins/gbp/gbp_contract.c deleted file mode 100644 index dd433f28a84..00000000000 --- a/src/plugins/gbp/gbp_contract.c +++ /dev/null @@ -1,819 +0,0 @@ -/* - * gbp.h : Group Based Policy - * - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp.h> -#include <plugins/gbp/gbp_bridge_domain.h> -#include <plugins/gbp/gbp_route_domain.h> -#include <plugins/gbp/gbp_policy_dpo.h> -#include <plugins/gbp/gbp_contract.h> - -#include <vnet/dpo/load_balance.h> -#include <vnet/dpo/drop_dpo.h> - -char *gbp_contract_error_strings[] = { -#define _(sym,string) string, - foreach_gbp_contract_error -#undef _ -}; - -/** - * Single contract DB instance - */ -gbp_contract_db_t gbp_contract_db; - -gbp_contract_t *gbp_contract_pool; - -vlib_log_class_t gc_logger; - -fib_node_type_t gbp_next_hop_fib_type; - -gbp_rule_t *gbp_rule_pool; -gbp_next_hop_t *gbp_next_hop_pool; - -#define GBP_CONTRACT_DBG(...) \ - vlib_log_notice (gc_logger, __VA_ARGS__); - -/* Adjacency packet/byte counters indexed by adjacency index. */ -vlib_combined_counter_main_t gbp_contract_permit_counters = { - .name = "gbp-contracts-permit", - .stat_segment_name = "/net/gbp/contract/permit", -}; - -vlib_combined_counter_main_t gbp_contract_drop_counters = { - .name = "gbp-contracts-drop", - .stat_segment_name = "/net/gbp/contract/drop", -}; - -index_t -gbp_rule_alloc (gbp_rule_action_t action, - gbp_hash_mode_t hash_mode, index_t * nhs) -{ - gbp_rule_t *gu; - - pool_get_zero (gbp_rule_pool, gu); - - gu->gu_hash_mode = hash_mode; - gu->gu_nhs = nhs; - gu->gu_action = action; - - return (gu - gbp_rule_pool); -} - -void -gbp_rule_free (index_t gui) -{ - pool_put_index (gbp_rule_pool, gui); -} - -index_t -gbp_next_hop_alloc (const ip46_address_t * ip, - index_t grd, const mac_address_t * mac, index_t gbd) -{ - fib_protocol_t fproto; - gbp_next_hop_t *gnh; - - pool_get_zero (gbp_next_hop_pool, gnh); - - fib_node_init (&gnh->gnh_node, gbp_next_hop_fib_type); - - ip46_address_copy (&gnh->gnh_ip, ip); - mac_address_copy (&gnh->gnh_mac, mac); - - gnh->gnh_rd = grd; - gnh->gnh_bd = gbd; - - FOR_EACH_FIB_IP_PROTOCOL (fproto) gnh->gnh_ai[fproto] = INDEX_INVALID; - - return (gnh - gbp_next_hop_pool); -} - -static inline gbp_next_hop_t * -gbp_next_hop_get (index_t gui) -{ - return (pool_elt_at_index (gbp_next_hop_pool, gui)); -} - -static void -gbp_contract_rules_free (index_t * rules) -{ - index_t *gui, *gnhi; - - vec_foreach (gui, rules) - { - gbp_policy_node_t pnode; - fib_protocol_t fproto; - gbp_next_hop_t *gnh; - gbp_rule_t *gu; - - gu = gbp_rule_get (*gui); - - FOR_EACH_GBP_POLICY_NODE (pnode) - { - FOR_EACH_FIB_IP_PROTOCOL (fproto) - { - dpo_reset (&gu->gu_dpo[pnode][fproto]); - dpo_reset (&gu->gu_dpo[pnode][fproto]); - } - } - - vec_foreach (gnhi, gu->gu_nhs) - { - fib_protocol_t fproto; - - gnh = gbp_next_hop_get (*gnhi); - gbp_bridge_domain_unlock (gnh->gnh_bd); - gbp_route_domain_unlock (gnh->gnh_rd); - gbp_endpoint_child_remove (gnh->gnh_ge, gnh->gnh_sibling); - gbp_endpoint_unlock (GBP_ENDPOINT_SRC_RR, gnh->gnh_ge); - - FOR_EACH_FIB_IP_PROTOCOL (fproto) - { - adj_unlock (gnh->gnh_ai[fproto]); - } - } - - gbp_rule_free (*gui); - } - vec_free (rules); -} - -static u8 * -format_gbp_next_hop (u8 * s, va_list * args) -{ - index_t gnhi = va_arg (*args, index_t); - gbp_next_hop_t *gnh; - - gnh = gbp_next_hop_get (gnhi); - - s = format (s, "%U, %U, %U EP:%d", - format_mac_address_t, &gnh->gnh_mac, - format_gbp_bridge_domain, gnh->gnh_bd, - format_ip46_address, &gnh->gnh_ip, IP46_TYPE_ANY, gnh->gnh_ge); - - return (s); -} - -u8 * -format_gbp_rule_action (u8 * s, va_list * args) -{ - gbp_rule_action_t action = va_arg (*args, gbp_rule_action_t); - - switch (action) - { -#define _(v,a) case GBP_RULE_##v: return (format (s, "%s", a)); - foreach_gbp_rule_action -#undef _ - } - - return (format (s, "unknown")); -} - -static u8 * -format_gbp_hash_mode (u8 * s, va_list * args) -{ - gbp_hash_mode_t hash_mode = va_arg (*args, gbp_hash_mode_t); - - switch (hash_mode) - { -#define _(v,a) case GBP_HASH_MODE_##v: return (format (s, "%s", a)); - foreach_gbp_hash_mode -#undef _ - } - - return (format (s, "unknown")); -} - -static u8 * -format_gbp_policy_node (u8 * s, va_list * args) -{ - gbp_policy_node_t action = va_arg (*args, gbp_policy_node_t); - - switch (action) - { -#define _(v,a) case GBP_POLICY_NODE_##v: return (format (s, "%s", a)); - foreach_gbp_policy_node -#undef _ - } - - return (format (s, "unknown")); -} - -static u8 * -format_gbp_rule (u8 * s, va_list * args) -{ - index_t gui = va_arg (*args, index_t); - gbp_policy_node_t pnode; - fib_protocol_t fproto; - gbp_rule_t *gu; - index_t *gnhi; - - gu = gbp_rule_get (gui); - s = format (s, "%U", format_gbp_rule_action, gu->gu_action); - - switch (gu->gu_action) - { - case GBP_RULE_PERMIT: - case GBP_RULE_DENY: - return (s); - case GBP_RULE_REDIRECT: - s = format (s, ", %U", format_gbp_hash_mode, gu->gu_hash_mode); - break; - } - - vec_foreach (gnhi, gu->gu_nhs) - { - s = format (s, "\n [%U]", format_gbp_next_hop, *gnhi); - } - - FOR_EACH_GBP_POLICY_NODE (pnode) - { - s = format (s, "\n policy-%U", format_gbp_policy_node, pnode); - - FOR_EACH_FIB_IP_PROTOCOL (fproto) - { - if (dpo_id_is_valid (&gu->gu_dpo[pnode][fproto])) - { - s = - format (s, "\n %U", format_dpo_id, - &gu->gu_dpo[pnode][fproto], 8); - } - } - } - - return (s); -} - -static void -gbp_contract_mk_adj (gbp_next_hop_t * gnh, fib_protocol_t fproto) -{ - ethernet_header_t *eth; - gbp_endpoint_t *ge; - index_t old_ai; - u8 *rewrite; - - old_ai = gnh->gnh_ai[fproto]; - rewrite = NULL; - vec_validate (rewrite, sizeof (*eth) - 1); - eth = (ethernet_header_t *) rewrite; - - GBP_CONTRACT_DBG ("...mk-adj: %U", format_gbp_next_hop, - gnh - gbp_next_hop_pool); - - ge = gbp_endpoint_get (gnh->gnh_ge); - - eth->type = clib_host_to_net_u16 ((fproto == FIB_PROTOCOL_IP4 ? - ETHERNET_TYPE_IP4 : ETHERNET_TYPE_IP6)); - mac_address_to_bytes (gbp_route_domain_get_local_mac (), eth->src_address); - mac_address_to_bytes (&gnh->gnh_mac, eth->dst_address); - - gnh->gnh_ai[fproto] = - adj_nbr_add_or_lock_w_rewrite (fproto, - fib_proto_to_link (fproto), - &gnh->gnh_ip, - gbp_itf_get_sw_if_index (ge-> - ge_fwd.gef_itf), - rewrite); - - adj_unlock (old_ai); -} - -static flow_hash_config_t -gbp_contract_mk_lb_hp (gbp_hash_mode_t gu_hash_mode) -{ - switch (gu_hash_mode) - { - case GBP_HASH_MODE_SRC_IP: - return IP_FLOW_HASH_SRC_ADDR; - case GBP_HASH_MODE_DST_IP: - return IP_FLOW_HASH_DST_ADDR; - case GBP_HASH_MODE_SYMMETRIC: - return (IP_FLOW_HASH_SRC_ADDR | IP_FLOW_HASH_DST_ADDR | - IP_FLOW_HASH_PROTO | IP_FLOW_HASH_SYMMETRIC); - } - - return 0; -} - -static void -gbp_contract_mk_lb (index_t gui, fib_protocol_t fproto) -{ - load_balance_path_t *paths = NULL; - gbp_policy_node_t pnode; - gbp_next_hop_t *gnh; - dpo_proto_t dproto; - gbp_rule_t *gu; - u32 ii; - - u32 policy_nodes[] = { - [GBP_POLICY_NODE_L2] = gbp_policy_port_node.index, - [GBP_POLICY_NODE_IP4] = ip4_gbp_policy_dpo_node.index, - [GBP_POLICY_NODE_IP6] = ip6_gbp_policy_dpo_node.index, - }; - - GBP_CONTRACT_DBG ("..mk-lb: %U", format_gbp_rule, gui); - - gu = gbp_rule_get (gui); - dproto = fib_proto_to_dpo (fproto); - - if (GBP_RULE_REDIRECT != gu->gu_action) - return; - - vec_foreach_index (ii, gu->gu_nhs) - { - gnh = gbp_next_hop_get (gu->gu_nhs[ii]); - - gbp_contract_mk_adj (gnh, FIB_PROTOCOL_IP4); - gbp_contract_mk_adj (gnh, FIB_PROTOCOL_IP6); - } - - FOR_EACH_GBP_POLICY_NODE (pnode) - { - vec_validate (paths, vec_len (gu->gu_nhs) - 1); - - vec_foreach_index (ii, gu->gu_nhs) - { - gnh = gbp_next_hop_get (gu->gu_nhs[ii]); - - paths[ii].path_index = FIB_NODE_INDEX_INVALID; - paths[ii].path_weight = 1; - dpo_set (&paths[ii].path_dpo, DPO_ADJACENCY, - dproto, gnh->gnh_ai[fproto]); - } - - if (!dpo_id_is_valid (&gu->gu_dpo[pnode][fproto])) - { - dpo_id_t dpo = DPO_INVALID; - - dpo_set (&dpo, DPO_LOAD_BALANCE, dproto, - load_balance_create (vec_len (paths), - dproto, - gbp_contract_mk_lb_hp - (gu->gu_hash_mode))); - dpo_stack_from_node (policy_nodes[pnode], &gu->gu_dpo[pnode][fproto], - &dpo); - dpo_reset (&dpo); - } - - load_balance_multipath_update (&gu->gu_dpo[pnode][fproto], - paths, LOAD_BALANCE_FLAG_NONE); - vec_free (paths); - } -} - -static void -gbp_contract_mk_one_lb (index_t gui) -{ - gbp_contract_mk_lb (gui, FIB_PROTOCOL_IP4); - gbp_contract_mk_lb (gui, FIB_PROTOCOL_IP6); -} - -static int -gbp_contract_next_hop_resolve (index_t gui, index_t gnhi) -{ - gbp_bridge_domain_t *gbd; - gbp_next_hop_t *gnh; - ip46_address_t *ips; - int rv; - - ips = NULL; - gnh = gbp_next_hop_get (gnhi); - gbd = gbp_bridge_domain_get (gnh->gnh_bd); - - gnh->gnh_gu = gui; - vec_add1 (ips, gnh->gnh_ip); - - /* - * source the endpoint this contract needs to forward via. - * give ofrwarding details via the spine proxy. if this EP is known - * to us, then since we source here with a low priority, the learned - * info will take precedenc. - */ - rv = gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_RR, - gbd->gb_uu_fwd_sw_if_index, - ips, - &gnh->gnh_mac, - gnh->gnh_bd, gnh->gnh_rd, SCLASS_INVALID, - GBP_ENDPOINT_FLAG_NONE, NULL, NULL, - &gnh->gnh_ge); - - if (0 == rv) - { - gnh->gnh_sibling = gbp_endpoint_child_add (gnh->gnh_ge, - gbp_next_hop_fib_type, gnhi); - } - - GBP_CONTRACT_DBG ("..resolve: %d: %d: %U", gui, gnhi, format_gbp_next_hop, - gnhi); - - vec_free (ips); - return (rv); -} - -static void -gbp_contract_rule_resolve (index_t gui) -{ - gbp_rule_t *gu; - index_t *gnhi; - - gu = gbp_rule_get (gui); - - GBP_CONTRACT_DBG ("..resolve: %U", format_gbp_rule, gui); - - vec_foreach (gnhi, gu->gu_nhs) - { - gbp_contract_next_hop_resolve (gui, *gnhi); - } -} - -static void -gbp_contract_resolve (index_t * guis) -{ - index_t *gui; - - vec_foreach (gui, guis) - { - gbp_contract_rule_resolve (*gui); - } -} - -static void -gbp_contract_mk_lbs (index_t * guis) -{ - index_t *gui; - - vec_foreach (gui, guis) - { - gbp_contract_mk_one_lb (*gui); - } -} - -int -gbp_contract_update (gbp_scope_t scope, - sclass_t sclass, - sclass_t dclass, - u32 acl_index, - index_t * rules, - u16 * allowed_ethertypes, u32 * stats_index) -{ - gbp_main_t *gm = &gbp_main; - u32 *acl_vec = NULL; - gbp_contract_t *gc; - index_t gci; - uword *p; - - gbp_contract_key_t key = { - .gck_scope = scope, - .gck_src = sclass, - .gck_dst = dclass, - }; - - if (~0 == gm->gbp_acl_user_id) - { - acl_plugin_exports_init (&gm->acl_plugin); - gm->gbp_acl_user_id = - gm->acl_plugin.register_user_module ("GBP ACL", "src-epg", "dst-epg"); - } - - p = hash_get (gbp_contract_db.gc_hash, key.as_u64); - if (p != NULL) - { - gci = p[0]; - gc = gbp_contract_get (gci); - gbp_contract_rules_free (gc->gc_rules); - gbp_main.acl_plugin.put_lookup_context_index (gc->gc_lc_index); - gc->gc_rules = NULL; - vec_free (gc->gc_allowed_ethertypes); - } - else - { - pool_get_zero (gbp_contract_pool, gc); - gc->gc_key = key; - gci = gc - gbp_contract_pool; - hash_set (gbp_contract_db.gc_hash, key.as_u64, gci); - - vlib_validate_combined_counter (&gbp_contract_drop_counters, gci); - vlib_zero_combined_counter (&gbp_contract_drop_counters, gci); - vlib_validate_combined_counter (&gbp_contract_permit_counters, gci); - vlib_zero_combined_counter (&gbp_contract_permit_counters, gci); - } - - GBP_CONTRACT_DBG ("update: %U", format_gbp_contract, gci); - - gc->gc_rules = rules; - gc->gc_allowed_ethertypes = allowed_ethertypes; - gbp_contract_resolve (gc->gc_rules); - gbp_contract_mk_lbs (gc->gc_rules); - - gc->gc_acl_index = acl_index; - gc->gc_lc_index = - gm->acl_plugin.get_lookup_context_index (gm->gbp_acl_user_id, - sclass, dclass); - - vec_add1 (acl_vec, gc->gc_acl_index); - gm->acl_plugin.set_acl_vec_for_context (gc->gc_lc_index, acl_vec); - vec_free (acl_vec); - - *stats_index = gci; - - return (0); -} - -int -gbp_contract_delete (gbp_scope_t scope, sclass_t sclass, sclass_t dclass) -{ - gbp_contract_key_t key = { - .gck_scope = scope, - .gck_src = sclass, - .gck_dst = dclass, - }; - gbp_contract_t *gc; - uword *p; - - p = hash_get (gbp_contract_db.gc_hash, key.as_u64); - if (p != NULL) - { - gc = gbp_contract_get (p[0]); - - gbp_contract_rules_free (gc->gc_rules); - gbp_main.acl_plugin.put_lookup_context_index (gc->gc_lc_index); - vec_free (gc->gc_allowed_ethertypes); - - hash_unset (gbp_contract_db.gc_hash, key.as_u64); - pool_put (gbp_contract_pool, gc); - - return (0); - } - - return (VNET_API_ERROR_NO_SUCH_ENTRY); -} - -void -gbp_contract_walk (gbp_contract_cb_t cb, void *ctx) -{ - gbp_contract_t *gc; - - /* *INDENT-OFF* */ - pool_foreach (gc, gbp_contract_pool) - { - if (!cb(gc, ctx)) - break; - } - /* *INDENT-ON* */ -} - -static clib_error_t * -gbp_contract_cli (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - sclass_t sclass = SCLASS_INVALID, dclass = SCLASS_INVALID; - u32 acl_index = ~0, stats_index, scope; - u8 add = 1; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "add")) - add = 1; - else if (unformat (input, "del")) - add = 0; - else if (unformat (input, "scope %d", &scope)) - ; - else if (unformat (input, "sclass %d", &sclass)) - ; - else if (unformat (input, "dclass %d", &dclass)) - ; - else if (unformat (input, "acl-index %d", &acl_index)) - ; - else - break; - } - - if (SCLASS_INVALID == sclass) - return clib_error_return (0, "Source EPG-ID must be specified"); - if (SCLASS_INVALID == dclass) - return clib_error_return (0, "Destination EPG-ID must be specified"); - - if (add) - { - gbp_contract_update (scope, sclass, dclass, acl_index, - NULL, NULL, &stats_index); - } - else - { - gbp_contract_delete (scope, sclass, dclass); - } - - return (NULL); -} - -/*? - * Configure a GBP Contract - * - * @cliexpar - * @cliexstart{set gbp contract [del] src-epg <ID> dst-epg <ID> acl-index <ACL>} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_contract_cli_node, static) = -{ - .path = "gbp contract", - .short_help = - "gbp contract [del] src-epg <ID> dst-epg <ID> acl-index <ACL>", - .function = gbp_contract_cli, -}; -/* *INDENT-ON* */ - -static u8 * -format_gbp_contract_key (u8 * s, va_list * args) -{ - gbp_contract_key_t *gck = va_arg (*args, gbp_contract_key_t *); - - s = format (s, "{%d,%d,%d}", gck->gck_scope, gck->gck_src, gck->gck_dst); - - return (s); -} - -u8 * -format_gbp_contract (u8 * s, va_list * args) -{ - index_t gci = va_arg (*args, index_t); - vlib_counter_t counts; - gbp_contract_t *gc; - index_t *gui; - u16 *et; - - gc = gbp_contract_get (gci); - - s = format (s, "[%d] %U: acl-index:%d", - gci, format_gbp_contract_key, &gc->gc_key, gc->gc_acl_index); - - s = format (s, "\n rules:"); - vec_foreach (gui, gc->gc_rules) - { - s = format (s, "\n %d: %U", *gui, format_gbp_rule, *gui); - } - - s = format (s, "\n allowed-ethertypes:"); - s = format (s, "\n ["); - vec_foreach (et, gc->gc_allowed_ethertypes) - { - int host_et = clib_net_to_host_u16 (*et); - if (0 != host_et) - s = format (s, "0x%x, ", host_et); - } - s = format (s, "]"); - - s = format (s, "\n stats:"); - vlib_get_combined_counter (&gbp_contract_drop_counters, gci, &counts); - s = format (s, "\n drop:[%Ld:%Ld]", counts.packets, counts.bytes); - vlib_get_combined_counter (&gbp_contract_permit_counters, gci, &counts); - s = format (s, "\n permit:[%Ld:%Ld]", counts.packets, counts.bytes); - - s = format (s, "]"); - - return (s); -} - -static clib_error_t * -gbp_contract_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - gbp_contract_t *gc; - u32 src, dst; - index_t gci; - - src = dst = SCLASS_INVALID; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "src %d", &src)) - ; - else if (unformat (input, "dst %d", &dst)) - ; - else - break; - } - - vlib_cli_output (vm, "Contracts:"); - - /* *INDENT-OFF* */ - pool_foreach (gc, gbp_contract_pool) - { - gci = gc - gbp_contract_pool; - - if (SCLASS_INVALID != src && SCLASS_INVALID != dst) - { - if (gc->gc_key.gck_src == src && - gc->gc_key.gck_dst == dst) - vlib_cli_output (vm, " %U", format_gbp_contract, gci); - } - else if (SCLASS_INVALID != src) - { - if (gc->gc_key.gck_src == src) - vlib_cli_output (vm, " %U", format_gbp_contract, gci); - } - else if (SCLASS_INVALID != dst) - { - if (gc->gc_key.gck_dst == dst) - vlib_cli_output (vm, " %U", format_gbp_contract, gci); - } - else - vlib_cli_output (vm, " %U", format_gbp_contract, gci); - } - /* *INDENT-ON* */ - - return (NULL); -} - -/*? - * Show Group Based Policy Contracts - * - * @cliexpar - * @cliexstart{show gbp contract} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_contract_show_node, static) = { - .path = "show gbp contract", - .short_help = "show gbp contract [src <SRC>] [dst <DST>]\n", - .function = gbp_contract_show, -}; -/* *INDENT-ON* */ - -static fib_node_t * -gbp_next_hop_get_node (fib_node_index_t index) -{ - gbp_next_hop_t *gnh; - - gnh = gbp_next_hop_get (index); - - return (&gnh->gnh_node); -} - -static void -gbp_next_hop_last_lock_gone (fib_node_t * node) -{ - ASSERT (0); -} - -static gbp_next_hop_t * -gbp_next_hop_from_fib_node (fib_node_t * node) -{ - ASSERT (gbp_next_hop_fib_type == node->fn_type); - return ((gbp_next_hop_t *) node); -} - -static fib_node_back_walk_rc_t -gbp_next_hop_back_walk_notify (fib_node_t * node, - fib_node_back_walk_ctx_t * ctx) -{ - gbp_next_hop_t *gnh; - - gnh = gbp_next_hop_from_fib_node (node); - - gbp_contract_mk_one_lb (gnh->gnh_gu); - - return (FIB_NODE_BACK_WALK_CONTINUE); -} - -/* - * The FIB path's graph node virtual function table - */ -static const fib_node_vft_t gbp_next_hop_vft = { - .fnv_get = gbp_next_hop_get_node, - .fnv_last_lock = gbp_next_hop_last_lock_gone, - .fnv_back_walk = gbp_next_hop_back_walk_notify, - // .fnv_mem_show = fib_path_memory_show, -}; - -static clib_error_t * -gbp_contract_init (vlib_main_t * vm) -{ - gc_logger = vlib_log_register_class ("gbp", "con"); - gbp_next_hop_fib_type = fib_node_register_new_type (&gbp_next_hop_vft); - - return (NULL); -} - -VLIB_INIT_FUNCTION (gbp_contract_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_contract.h b/src/plugins/gbp/gbp_contract.h deleted file mode 100644 index 1e74db60116..00000000000 --- a/src/plugins/gbp/gbp_contract.h +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_CONTRACT_H__ -#define __GBP_CONTRACT_H__ - -#include <plugins/gbp/gbp.h> -#include <plugins/gbp/gbp_types.h> - -#define foreach_gbp_contract_error \ - _(ALLOW_NO_SCLASS, "allow-no-sclass") \ - _(ALLOW_INTRA, "allow-intra-sclass") \ - _(ALLOW_A_BIT, "allow-a-bit-set") \ - _(ALLOW_SCLASS_1, "allow-sclass-1") \ - _(ALLOW_CONTRACT, "allow-contract") \ - _(DROP_CONTRACT, "drop-contract") \ - _(DROP_ETHER_TYPE, "drop-ether-type") \ - _(DROP_NO_CONTRACT, "drop-no-contract") \ - _(DROP_NO_DCLASS, "drop-no-dclass") \ - _(DROP_NO_RULE, "drop-no-rule") - -typedef enum -{ -#define _(sym,str) GBP_CONTRACT_ERROR_##sym, - foreach_gbp_contract_error -#undef _ - GBP_CONTRACT_N_ERROR, -#define GBP_CONTRACT_N_ERROR GBP_CONTRACT_N_ERROR -} gbp_contract_error_t; - -extern char *gbp_contract_error_strings[GBP_CONTRACT_N_ERROR]; - -/** - * The key for an Contract - */ -typedef struct gbp_contract_key_t_ -{ - union - { - struct - { - gbp_scope_t gck_scope; - /** - * source and destination EPGs for which the ACL applies - */ - sclass_t gck_src; - sclass_t gck_dst; - }; - u64 as_u64; - }; -} gbp_contract_key_t; - -typedef struct gbp_next_hop_t_ -{ - fib_node_t gnh_node; - ip46_address_t gnh_ip; - mac_address_t gnh_mac; - index_t gnh_gu; - index_t gnh_bd; - index_t gnh_rd; - u32 gnh_ge; - u32 gnh_sibling; - index_t gnh_ai[FIB_PROTOCOL_IP_MAX]; -} gbp_next_hop_t; - -#define foreach_gbp_hash_mode \ - _(SRC_IP, "src-ip") \ - _(DST_IP, "dst-ip") \ - _(SYMMETRIC, "symmetric") - -typedef enum gbp_hash_mode_t_ -{ -#define _(v,s) GBP_HASH_MODE_##v, - foreach_gbp_hash_mode -#undef _ -} gbp_hash_mode_t; - -#define foreach_gbp_rule_action \ - _(PERMIT, "permit") \ - _(DENY, "deny") \ - _(REDIRECT, "redirect") - -typedef enum gbp_rule_action_t_ -{ -#define _(v,s) GBP_RULE_##v, - foreach_gbp_rule_action -#undef _ -} gbp_rule_action_t; - -#define foreach_gbp_policy_node \ - _(L2, "L2") \ - _(IP4, "ip4") \ - _(IP6, "ip6") - -typedef enum gbp_policy_node_t_ -{ -#define _(v,s) GBP_POLICY_NODE_##v, - foreach_gbp_policy_node -#undef _ -} gbp_policy_node_t; -#define GBP_POLICY_N_NODES (GBP_POLICY_NODE_IP6+1) - -#define FOR_EACH_GBP_POLICY_NODE(pnode) \ - for (pnode = GBP_POLICY_NODE_L2; pnode < GBP_POLICY_N_NODES; pnode++) - -typedef struct gbp_rule_t_ -{ - gbp_rule_action_t gu_action; - gbp_hash_mode_t gu_hash_mode; - index_t *gu_nhs; - - /** - * DPO of the load-balance object used to redirect - */ - dpo_id_t gu_dpo[GBP_POLICY_N_NODES][FIB_PROTOCOL_IP_MAX]; -} gbp_rule_t; - -/** - * A Group Based Policy Contract. - * Determines the ACL that applies to traffic pass between two endpoint groups - */ -typedef struct gbp_contract_t_ -{ - /** - * source and destination EPGs - */ - gbp_contract_key_t gc_key; - - u32 gc_acl_index; - u32 gc_lc_index; - - /** - * The ACL to apply for packets from the source to the destination EPG - */ - index_t *gc_rules; - - /** - * An ethertype whitelist - */ - u16 *gc_allowed_ethertypes; -} gbp_contract_t; - -/** - * EPG src,dst pair to ACL mapping table, aka contract DB - */ -typedef struct gbp_contract_db_t_ -{ - /** - * We can form a u64 key from the pair, so use a simple hash table - */ - uword *gc_hash; -} gbp_contract_db_t; - -extern int gbp_contract_update (gbp_scope_t scope, - sclass_t sclass, - sclass_t dclass, - u32 acl_index, - index_t * rules, - u16 * allowed_ethertypes, u32 * stats_index); -extern int gbp_contract_delete (gbp_scope_t scope, sclass_t sclass, - sclass_t dclass); - -extern index_t gbp_rule_alloc (gbp_rule_action_t action, - gbp_hash_mode_t hash_mode, index_t * nhs); -extern void gbp_rule_free (index_t gui); -extern index_t gbp_next_hop_alloc (const ip46_address_t * ip, - index_t grd, - const mac_address_t * mac, index_t gbd); - -typedef int (*gbp_contract_cb_t) (gbp_contract_t * gbpe, void *ctx); -extern void gbp_contract_walk (gbp_contract_cb_t bgpe, void *ctx); - -extern u8 *format_gbp_rule_action (u8 * s, va_list * args); -extern u8 *format_gbp_contract (u8 * s, va_list * args); - -/** - * DP functions and databases - */ -extern gbp_contract_db_t gbp_contract_db; - -always_inline index_t -gbp_contract_find (gbp_contract_key_t * key) -{ - uword *p; - - p = hash_get (gbp_contract_db.gc_hash, key->as_u64); - - if (NULL != p) - return (p[0]); - - return (INDEX_INVALID); -} - -extern gbp_contract_t *gbp_contract_pool; - -always_inline gbp_contract_t * -gbp_contract_get (index_t gci) -{ - return (pool_elt_at_index (gbp_contract_pool, gci)); -} - -extern gbp_rule_t *gbp_rule_pool; - -always_inline gbp_rule_t * -gbp_rule_get (index_t gui) -{ - return (pool_elt_at_index (gbp_rule_pool, gui)); -} - -extern vlib_combined_counter_main_t gbp_contract_permit_counters; -extern vlib_combined_counter_main_t gbp_contract_drop_counters; - -typedef enum -{ - GBP_CONTRACT_APPLY_L2, - GBP_CONTRACT_APPLY_IP4, - GBP_CONTRACT_APPLY_IP6, -} gbp_contract_apply_type_t; - -static_always_inline gbp_rule_action_t -gbp_contract_apply (vlib_main_t * vm, gbp_main_t * gm, - gbp_contract_key_t * key, vlib_buffer_t * b, - gbp_rule_t ** rule, u32 * intra, u32 * sclass1, - u32 * acl_match, u32 * rule_match, - gbp_contract_error_t * err, - gbp_contract_apply_type_t type) -{ - fa_5tuple_opaque_t fa_5tuple; - const gbp_contract_t *contract; - index_t contract_index; - u32 acl_pos, trace_bitmap; - u16 etype; - u8 ip6, action; - - *rule = 0; - trace_bitmap = 0; - - if (key->gck_src == key->gck_dst) - { - /* intra-epg allowed */ - (*intra)++; - *err = GBP_CONTRACT_ERROR_ALLOW_INTRA; - return GBP_RULE_PERMIT; - } - - if (1 == key->gck_src || 1 == key->gck_dst) - { - /* sclass 1 allowed */ - (*sclass1)++; - *err = GBP_CONTRACT_ERROR_ALLOW_SCLASS_1; - return GBP_RULE_PERMIT; - } - - /* look for contract */ - contract_index = gbp_contract_find (key); - if (INDEX_INVALID == contract_index) - { - *err = GBP_CONTRACT_ERROR_DROP_NO_CONTRACT; - return GBP_RULE_DENY; - } - - contract = gbp_contract_get (contract_index); - - *err = GBP_CONTRACT_ERROR_DROP_CONTRACT; - - switch (type) - { - case GBP_CONTRACT_APPLY_IP4: - ip6 = 0; - break; - case GBP_CONTRACT_APPLY_IP6: - ip6 = 1; - break; - case GBP_CONTRACT_APPLY_L2: - { - /* check ethertype */ - etype = - ((u16 *) (vlib_buffer_get_current (b) + - vnet_buffer (b)->l2.l2_len))[-1]; - - if (~0 == vec_search (contract->gc_allowed_ethertypes, etype)) - { - *err = GBP_CONTRACT_ERROR_DROP_ETHER_TYPE; - goto contract_deny; - } - - switch (clib_net_to_host_u16 (etype)) - { - case ETHERNET_TYPE_IP4: - ip6 = 0; - break; - case ETHERNET_TYPE_IP6: - ip6 = 1; - break; - default: - goto contract_deny; - } - } - break; - } - - /* check ACL */ - action = 0; - acl_plugin_fill_5tuple_inline (gm->acl_plugin.p_acl_main, - contract->gc_lc_index, b, ip6, - GBP_CONTRACT_APPLY_L2 != type /* input */ , - GBP_CONTRACT_APPLY_L2 == type /* l2_path */ , - &fa_5tuple); - acl_plugin_match_5tuple_inline (gm->acl_plugin.p_acl_main, - contract->gc_lc_index, &fa_5tuple, ip6, - &action, &acl_pos, acl_match, rule_match, - &trace_bitmap); - if (action <= 0) - goto contract_deny; - - if (PREDICT_FALSE (*rule_match >= vec_len (contract->gc_rules))) - { - *err = GBP_CONTRACT_ERROR_DROP_NO_RULE; - goto contract_deny; - } - - *rule = gbp_rule_get (contract->gc_rules[*rule_match]); - switch ((*rule)->gu_action) - { - case GBP_RULE_PERMIT: - case GBP_RULE_REDIRECT: - *err = GBP_CONTRACT_ERROR_ALLOW_CONTRACT; - vlib_increment_combined_counter (&gbp_contract_permit_counters, - vm->thread_index, contract_index, 1, - vlib_buffer_length_in_chain (vm, b)); - return (*rule)->gu_action; - case GBP_RULE_DENY: - break; - } - -contract_deny: - vlib_increment_combined_counter (&gbp_contract_drop_counters, - vm->thread_index, contract_index, 1, - vlib_buffer_length_in_chain (vm, b)); - return GBP_RULE_DENY; -} - -#endif /* __GBP_CONTRACT_H__ */ -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_endpoint.c b/src/plugins/gbp/gbp_endpoint.c deleted file mode 100644 index b0cf64ced2d..00000000000 --- a/src/plugins/gbp/gbp_endpoint.c +++ /dev/null @@ -1,1597 +0,0 @@ -/* - * gbp.h : Group Based Policy - * - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp_endpoint.h> -#include <plugins/gbp/gbp_endpoint_group.h> -#include <plugins/gbp/gbp_itf.h> -#include <plugins/gbp/gbp_scanner.h> -#include <plugins/gbp/gbp_bridge_domain.h> -#include <plugins/gbp/gbp_route_domain.h> -#include <plugins/gbp/gbp_policy_dpo.h> -#include <plugins/gbp/gbp_vxlan.h> - -#include <vnet/l2/l2_input.h> -#include <vnet/l2/l2_output.h> -#include <vnet/l2/feat_bitmap.h> -#include <vnet/l2/l2_fib.h> -#include <vnet/fib/fib_table.h> -#include <vnet/ip-neighbor/ip_neighbor.h> -#include <vnet/ip-neighbor/ip4_neighbor.h> -#include <vnet/ip-neighbor/ip6_neighbor.h> -#include <vnet/fib/fib_walk.h> -#include <vnet/vxlan-gbp/vxlan_gbp.h> - -static const char *gbp_endpoint_attr_names[] = GBP_ENDPOINT_ATTR_NAMES; - -/** - * EP DBs - */ -gbp_ep_db_t gbp_ep_db; - -static fib_source_t gbp_fib_source_hi; -static fib_source_t gbp_fib_source_low; -static fib_node_type_t gbp_endpoint_fib_type; -static vlib_log_class_t gbp_ep_logger; - -#define GBP_ENDPOINT_DBG(...) \ - vlib_log_debug (gbp_ep_logger, __VA_ARGS__); - -#define GBP_ENDPOINT_INFO(...) \ - vlib_log_notice (gbp_ep_logger, __VA_ARGS__); - -/** - * Pool of GBP endpoints - */ -gbp_endpoint_t *gbp_endpoint_pool; - -/** - * A count of the number of dynamic entries - */ -static u32 gbp_n_learnt_endpoints; - -#define FOR_EACH_GBP_ENDPOINT_ATTR(_item) \ - for (_item = GBP_ENDPOINT_ATTR_FIRST; \ - _item < GBP_ENDPOINT_ATTR_LAST; \ - _item++) - -u8 * -format_gbp_endpoint_flags (u8 * s, va_list * args) -{ - gbp_endpoint_attr_t attr; - gbp_endpoint_flags_t flags = va_arg (*args, gbp_endpoint_flags_t); - - FOR_EACH_GBP_ENDPOINT_ATTR (attr) - { - if ((1 << attr) & flags) - { - s = format (s, "%s,", gbp_endpoint_attr_names[attr]); - } - } - - return (s); -} - -int -gbp_endpoint_is_remote (const gbp_endpoint_t * ge) -{ - return (! !(ge->ge_fwd.gef_flags & GBP_ENDPOINT_FLAG_REMOTE)); -} - -int -gbp_endpoint_is_local (const gbp_endpoint_t * ge) -{ - return (!(ge->ge_fwd.gef_flags & GBP_ENDPOINT_FLAG_REMOTE)); -} - -int -gbp_endpoint_is_external (const gbp_endpoint_t * ge) -{ - return (! !(ge->ge_fwd.gef_flags & GBP_ENDPOINT_FLAG_EXTERNAL)); -} - -int -gbp_endpoint_is_learnt (const gbp_endpoint_t * ge) -{ - if (0 == vec_len (ge->ge_locs)) - return 0; - - /* DP is the highest source so if present it will be first */ - return (ge->ge_locs[0].gel_src == GBP_ENDPOINT_SRC_DP); -} - -static void -gbp_endpoint_extract_key_mac_itf (const clib_bihash_kv_16_8_t * key, - mac_address_t * mac, u32 * sw_if_index) -{ - mac_address_from_u64 (mac, key->key[0]); - *sw_if_index = key->key[1]; -} - -static void -gbp_endpoint_extract_key_ip_itf (const clib_bihash_kv_24_8_t * key, - ip46_address_t * ip, u32 * sw_if_index) -{ - ip->as_u64[0] = key->key[0]; - ip->as_u64[1] = key->key[1]; - *sw_if_index = key->key[2]; -} - -gbp_endpoint_t * -gbp_endpoint_find_ip (const ip46_address_t * ip, u32 fib_index) -{ - clib_bihash_kv_24_8_t key, value; - int rv; - - gbp_endpoint_mk_key_ip (ip, fib_index, &key); - - rv = clib_bihash_search_24_8 (&gbp_ep_db.ged_by_ip_rd, &key, &value); - - if (0 != rv) - return NULL; - - return (gbp_endpoint_get (value.value)); -} - -static void -gbp_endpoint_add_itf (u32 sw_if_index, index_t gei) -{ - vec_validate_init_empty (gbp_ep_db.ged_by_sw_if_index, sw_if_index, ~0); - - gbp_ep_db.ged_by_sw_if_index[sw_if_index] = gei; -} - -static bool -gbp_endpoint_add_mac (const mac_address_t * mac, u32 bd_index, index_t gei) -{ - clib_bihash_kv_16_8_t key; - int rv; - - gbp_endpoint_mk_key_mac (mac->bytes, bd_index, &key); - key.value = gei; - - rv = clib_bihash_add_del_16_8 (&gbp_ep_db.ged_by_mac_bd, &key, 1); - - - return (0 == rv); -} - -static bool -gbp_endpoint_add_ip (const ip46_address_t * ip, u32 fib_index, index_t gei) -{ - clib_bihash_kv_24_8_t key; - int rv; - - gbp_endpoint_mk_key_ip (ip, fib_index, &key); - key.value = gei; - - rv = clib_bihash_add_del_24_8 (&gbp_ep_db.ged_by_ip_rd, &key, 1); - - return (0 == rv); -} - -static void -gbp_endpoint_del_mac (const mac_address_t * mac, u32 bd_index) -{ - clib_bihash_kv_16_8_t key; - - gbp_endpoint_mk_key_mac (mac->bytes, bd_index, &key); - - clib_bihash_add_del_16_8 (&gbp_ep_db.ged_by_mac_bd, &key, 0); -} - -static void -gbp_endpoint_del_ip (const ip46_address_t * ip, u32 fib_index) -{ - clib_bihash_kv_24_8_t key; - - gbp_endpoint_mk_key_ip (ip, fib_index, &key); - - clib_bihash_add_del_24_8 (&gbp_ep_db.ged_by_ip_rd, &key, 0); -} - -static index_t -gbp_endpoint_index (const gbp_endpoint_t * ge) -{ - return (ge - gbp_endpoint_pool); -} - -static int -gbp_endpoint_ip_is_equal (const fib_prefix_t * fp, const ip46_address_t * ip) -{ - return (ip46_address_is_equal (ip, &fp->fp_addr)); -} - -static void -gbp_endpoint_ips_update (gbp_endpoint_t * ge, - const ip46_address_t * ips, - const gbp_route_domain_t * grd) -{ - const ip46_address_t *ip; - index_t gei, grdi; - - gei = gbp_endpoint_index (ge); - grdi = gbp_route_domain_index (grd); - - ASSERT ((ge->ge_key.gek_grd == INDEX_INVALID) || - (ge->ge_key.gek_grd == grdi)); - - vec_foreach (ip, ips) - { - if (~0 == vec_search_with_function (ge->ge_key.gek_ips, ip, - gbp_endpoint_ip_is_equal)) - { - fib_prefix_t *pfx; - - vec_add2 (ge->ge_key.gek_ips, pfx, 1); - fib_prefix_from_ip46_addr (ip, pfx); - - gbp_endpoint_add_ip (&pfx->fp_addr, - grd->grd_fib_index[pfx->fp_proto], gei); - } - ge->ge_key.gek_grd = grdi; - } -} - -static gbp_endpoint_t * -gbp_endpoint_alloc (const ip46_address_t * ips, - const gbp_route_domain_t * grd, - const mac_address_t * mac, - const gbp_bridge_domain_t * gbd) -{ - gbp_endpoint_t *ge; - index_t gei; - - pool_get_zero (gbp_endpoint_pool, ge); - - fib_node_init (&ge->ge_node, gbp_endpoint_fib_type); - gei = gbp_endpoint_index (ge); - ge->ge_key.gek_gbd = - ge->ge_key.gek_grd = ge->ge_fwd.gef_fib_index = INDEX_INVALID; - gbp_itf_hdl_reset (&ge->ge_fwd.gef_itf); - ge->ge_last_time = vlib_time_now (vlib_get_main ()); - ge->ge_key.gek_gbd = gbp_bridge_domain_index (gbd); - - if (NULL != mac) - { - mac_address_copy (&ge->ge_key.gek_mac, mac); - gbp_endpoint_add_mac (mac, gbd->gb_bd_index, gei); - } - gbp_endpoint_ips_update (ge, ips, grd); - - return (ge); -} - -static int -gbp_endpoint_loc_is_equal (gbp_endpoint_loc_t * a, gbp_endpoint_loc_t * b) -{ - return (a->gel_src == b->gel_src); -} - -static int -gbp_endpoint_loc_cmp_for_sort (gbp_endpoint_loc_t * a, gbp_endpoint_loc_t * b) -{ - return (a->gel_src - b->gel_src); -} - -static gbp_endpoint_loc_t * -gbp_endpoint_loc_find (gbp_endpoint_t * ge, gbp_endpoint_src_t src) -{ - gbp_endpoint_loc_t gel = { - .gel_src = src, - }; - u32 pos; - - pos = vec_search_with_function (ge->ge_locs, &gel, - gbp_endpoint_loc_is_equal); - - if (~0 != pos) - return (&ge->ge_locs[pos]); - - return NULL; -} - -static int -gbp_endpoint_loc_unlock (gbp_endpoint_t * ge, gbp_endpoint_loc_t * gel) -{ - u32 pos; - - gel->gel_locks--; - - if (0 == gel->gel_locks) - { - pos = gel - ge->ge_locs; - - vec_del1 (ge->ge_locs, pos); - if (vec_len (ge->ge_locs) > 1) - vec_sort_with_function (ge->ge_locs, gbp_endpoint_loc_cmp_for_sort); - - /* This could be the last lock, so don't access the EP from - * this point on */ - fib_node_unlock (&ge->ge_node); - - return (1); - } - return (0); -} - -static void -gbp_endpoint_loc_destroy (gbp_endpoint_loc_t * gel) -{ - gbp_endpoint_group_unlock (gel->gel_epg); - gbp_itf_unlock (&gel->gel_itf); -} - -static gbp_endpoint_loc_t * -gbp_endpoint_loc_find_or_add (gbp_endpoint_t * ge, gbp_endpoint_src_t src) -{ - gbp_endpoint_loc_t gel = { - .gel_src = src, - .gel_epg = INDEX_INVALID, - .gel_itf = GBP_ITF_HDL_INVALID, - .gel_locks = 0, - }; - u32 pos; - - pos = vec_search_with_function (ge->ge_locs, &gel, - gbp_endpoint_loc_is_equal); - - if (~0 == pos) - { - vec_add1 (ge->ge_locs, gel); - - if (vec_len (ge->ge_locs) > 1) - { - vec_sort_with_function (ge->ge_locs, gbp_endpoint_loc_cmp_for_sort); - - pos = vec_search_with_function (ge->ge_locs, &gel, - gbp_endpoint_loc_is_equal); - } - else - pos = 0; - - /* - * it's the sources and children that lock the endpoints - */ - fib_node_lock (&ge->ge_node); - } - - return (&ge->ge_locs[pos]); -} - -/** - * Find an EP inthe DBs and check that if we find it in the L2 DB - * it has the same IPs as this update - */ -static int -gbp_endpoint_find_for_update (const ip46_address_t * ips, - const gbp_route_domain_t * grd, - const mac_address_t * mac, - const gbp_bridge_domain_t * gbd, - gbp_endpoint_t ** ge) -{ - gbp_endpoint_t *l2_ge, *l3_ge, *tmp; - - l2_ge = l3_ge = NULL; - - if (NULL != mac && !mac_address_is_zero (mac)) - { - ASSERT (gbd); - l2_ge = gbp_endpoint_find_mac (mac->bytes, gbd->gb_bd_index); - } - if (NULL != ips && !ip46_address_is_zero (ips)) - { - const ip46_address_t *ip; - fib_protocol_t fproto; - - ASSERT (grd); - vec_foreach (ip, ips) - { - fproto = fib_proto_from_ip46 (ip46_address_get_type (ip)); - - tmp = gbp_endpoint_find_ip (ip, grd->grd_fib_index[fproto]); - - if (NULL == tmp) - /* not found */ - continue; - else if (NULL == l3_ge) - /* first match against an IP address */ - l3_ge = tmp; - else if (tmp == l3_ge) - /* another match against IP address that is the same endpoint */ - continue; - else - { - /* - * a match agains a different endpoint. - * this means the KEY of the EP is changing which is not allowed - */ - return (-1); - } - } - } - - if (NULL == l2_ge && NULL == l3_ge) - /* not found */ - *ge = NULL; - else if (NULL == l2_ge) - /* found at L3 */ - *ge = l3_ge; - else if (NULL == l3_ge) - /* found at L2 */ - *ge = l2_ge; - else - { - /* found both L3 and L2 - they must be the same else the KEY - * is changing - */ - if (l2_ge == l3_ge) - *ge = l2_ge; - else - return (-1); - } - - return (0); -} - -static gbp_endpoint_src_t -gbp_endpoint_get_best_src (const gbp_endpoint_t * ge) -{ - if (0 == vec_len (ge->ge_locs)) - return (GBP_ENDPOINT_SRC_MAX); - - return (ge->ge_locs[0].gel_src); -} - -static void -gbp_endpoint_n_learned (int n) -{ - gbp_n_learnt_endpoints += n; - - if (n > 0 && 1 == gbp_n_learnt_endpoints) - { - vlib_process_signal_event (vlib_get_main (), - gbp_scanner_node.index, - GBP_ENDPOINT_SCAN_START, 0); - } - if (n < 0 && 0 == gbp_n_learnt_endpoints) - { - vlib_process_signal_event (vlib_get_main (), - gbp_scanner_node.index, - GBP_ENDPOINT_SCAN_STOP, 0); - } -} - -static void -gbp_endpoint_loc_update (const gbp_endpoint_t * ge, - gbp_endpoint_loc_t * gel, - const gbp_bridge_domain_t * gb, - u32 sw_if_index, - index_t ggi, - gbp_endpoint_flags_t flags, - const ip46_address_t * tun_src, - const ip46_address_t * tun_dst) -{ - int was_learnt, is_learnt; - - gel->gel_locks++; - was_learnt = ! !(gel->gel_flags & GBP_ENDPOINT_FLAG_REMOTE); - gel->gel_flags = flags; - is_learnt = ! !(gel->gel_flags & GBP_ENDPOINT_FLAG_REMOTE); - - gbp_endpoint_n_learned (is_learnt - was_learnt); - - /* - * update the EPG - */ - gbp_endpoint_group_lock (ggi); - gbp_endpoint_group_unlock (gel->gel_epg); - gel->gel_epg = ggi; - - if (gel->gel_flags & GBP_ENDPOINT_FLAG_REMOTE) - { - if (NULL != tun_src) - ip46_address_copy (&gel->tun.gel_src, tun_src); - if (NULL != tun_dst) - ip46_address_copy (&gel->tun.gel_dst, tun_dst); - - if (ip46_address_is_multicast (&gel->tun.gel_src)) - { - /* - * we learnt the EP from the multicast tunnel. - * Create a unicast TEP from the packet's source - * and the fixed address of the BD's parent tunnel - */ - const gbp_vxlan_tunnel_t *gt; - - gt = gbp_vxlan_tunnel_get (gb->gb_vni); - - if (NULL != gt) - { - ip46_address_copy (&gel->tun.gel_src, >->gt_src); - sw_if_index = gt->gt_sw_if_index; - } - } - - /* - * the input interface may be the parent GBP-vxlan interface, - * create a child vlxan-gbp tunnel and use that as the endpoint's - * interface. - */ - gbp_itf_hdl_t old = gel->gel_itf; - - switch (gbp_vxlan_tunnel_get_type (sw_if_index)) - { - case GBP_VXLAN_TEMPLATE_TUNNEL: - gel->tun.gel_parent_sw_if_index = sw_if_index; - gel->gel_itf = gbp_vxlan_tunnel_clone_and_lock (sw_if_index, - &gel->tun.gel_src, - &gel->tun.gel_dst); - break; - case VXLAN_GBP_TUNNEL: - gel->tun.gel_parent_sw_if_index = - vxlan_gbp_tunnel_get_parent (sw_if_index); - gel->gel_itf = vxlan_gbp_tunnel_lock_itf (sw_if_index); - break; - } - - gbp_itf_unlock (&old); - } - else - { - gel->gel_itf = gbp_itf_l2_add_and_lock (sw_if_index, - ge->ge_key.gek_gbd); - } -} - -static void -gbb_endpoint_fwd_reset (gbp_endpoint_t * ge) -{ - const gbp_route_domain_t *grd; - const gbp_bridge_domain_t *gbd; - gbp_endpoint_fwd_t *gef; - const fib_prefix_t *pfx; - index_t *ai; - - gbd = gbp_bridge_domain_get (ge->ge_key.gek_gbd); - gef = &ge->ge_fwd; - - vec_foreach (pfx, ge->ge_key.gek_ips) - { - u32 fib_index; - - grd = gbp_route_domain_get (ge->ge_key.gek_grd); - fib_index = grd->grd_fib_index[pfx->fp_proto]; - - bd_add_del_ip_mac (gbd->gb_bd_index, fib_proto_to_ip46 (pfx->fp_proto), - &pfx->fp_addr, &ge->ge_key.gek_mac, 0); - - /* - * remove a host route - */ - if (gbp_endpoint_is_remote (ge)) - { - fib_table_entry_special_remove (fib_index, pfx, gbp_fib_source_hi); - } - - fib_table_entry_delete (fib_index, pfx, gbp_fib_source_low); - } - vec_foreach (ai, gef->gef_adjs) - { - adj_unlock (*ai); - } - - if (gbp_itf_hdl_is_valid (gef->gef_itf)) - { - l2fib_del_entry (ge->ge_key.gek_mac.bytes, - gbd->gb_bd_index, - gbp_itf_get_sw_if_index (gef->gef_itf)); - } - - gbp_itf_unlock (&gef->gef_itf); - vec_free (gef->gef_adjs); -} - -static void -gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) -{ - const gbp_bridge_domain_t *gbd; - const gbp_endpoint_group_t *gg; - const gbp_route_domain_t *grd; - gbp_endpoint_loc_t *gel; - gbp_endpoint_fwd_t *gef; - const fib_prefix_t *pfx; - index_t gei; - - /* - * locations are sort in source priority order - */ - gei = gbp_endpoint_index (ge); - gel = &ge->ge_locs[0]; - gef = &ge->ge_fwd; - gbd = gbp_bridge_domain_get (ge->ge_key.gek_gbd); - - gef->gef_flags = gel->gel_flags; - - if (INDEX_INVALID != gel->gel_epg) - { - gg = gbp_endpoint_group_get (gel->gel_epg); - gef->gef_sclass = gg->gg_sclass; - } - else - { - gg = NULL; - } - - gef->gef_itf = gbp_itf_clone_and_lock (gel->gel_itf); - - if (!mac_address_is_zero (&ge->ge_key.gek_mac)) - { - gbp_itf_l2_set_input_feature (gef->gef_itf, L2INPUT_FEAT_GBP_FWD); - - if (gbp_endpoint_is_remote (ge) || gbp_endpoint_is_external (ge)) - { - /* - * bridged packets to external endpoints should be classifed - * based on the EP's/BD's EPG - */ - gbp_itf_l2_set_output_feature (gef->gef_itf, - L2OUTPUT_FEAT_GBP_POLICY_MAC); - } - else - { - gbp_endpoint_add_itf (gbp_itf_get_sw_if_index (gef->gef_itf), gei); - gbp_itf_l2_set_output_feature (gef->gef_itf, - L2OUTPUT_FEAT_GBP_POLICY_PORT); - } - l2fib_add_entry (ge->ge_key.gek_mac.bytes, - gbd->gb_bd_index, - gbp_itf_get_sw_if_index (gef->gef_itf), - L2FIB_ENTRY_RESULT_FLAG_STATIC); - } - - vec_foreach (pfx, ge->ge_key.gek_ips) - { - ethernet_header_t *eth; - u32 ip_sw_if_index; - u32 fib_index; - u8 *rewrite; - index_t ai; - - rewrite = NULL; - grd = gbp_route_domain_get (ge->ge_key.gek_grd); - fib_index = grd->grd_fib_index[pfx->fp_proto]; - gef->gef_fib_index = fib_index; - - bd_add_del_ip_mac (gbd->gb_bd_index, fib_proto_to_ip46 (pfx->fp_proto), - &pfx->fp_addr, &ge->ge_key.gek_mac, 1); - - /* - * add a host route via the EPG's BVI we need this because the - * adj fib does not install, due to cover refinement check, since - * the BVI's prefix is /32 - */ - vec_validate (rewrite, sizeof (*eth) - 1); - eth = (ethernet_header_t *) rewrite; - - eth->type = clib_host_to_net_u16 ((pfx->fp_proto == FIB_PROTOCOL_IP4 ? - ETHERNET_TYPE_IP4 : - ETHERNET_TYPE_IP6)); - - if (gbp_endpoint_is_remote (ge)) - { - /* - * for dynamic EPs we must add the IP adjacency via the learned - * tunnel since the BD will not contain the EP's MAC since it was - * L3 learned. The dst MAC address used is the 'BD's MAC'. - */ - ip_sw_if_index = gbp_itf_get_sw_if_index (gef->gef_itf); - - mac_address_to_bytes (gbp_route_domain_get_local_mac (), - eth->src_address); - mac_address_to_bytes (gbp_route_domain_get_remote_mac (), - eth->dst_address); - } - else - { - /* - * for the static EPs we add the IP adjacency via the BVI - * knowing that the BD has the MAC address to route to and - * that policy will be applied on egress to the EP's port - */ - ip_sw_if_index = gbd->gb_bvi_sw_if_index; - - clib_memcpy (eth->src_address, - vnet_sw_interface_get_hw_address (vnet_get_main (), - ip_sw_if_index), - sizeof (eth->src_address)); - mac_address_to_bytes (&ge->ge_key.gek_mac, eth->dst_address); - } - - fib_table_entry_path_add (fib_index, pfx, - gbp_fib_source_low, - FIB_ENTRY_FLAG_NONE, - fib_proto_to_dpo (pfx->fp_proto), - &pfx->fp_addr, ip_sw_if_index, - ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE); - - ai = adj_nbr_add_or_lock_w_rewrite (pfx->fp_proto, - fib_proto_to_link (pfx->fp_proto), - &pfx->fp_addr, - ip_sw_if_index, rewrite); - vec_add1 (gef->gef_adjs, ai); - - /* - * if the endpoint is external then routed packet to it must be - * classifed to the BD's EPG. but this will happen anyway with - * the GBP_MAC classification. - */ - - if (NULL != gg) - { - if (gbp_endpoint_is_remote (ge)) - { - dpo_id_t policy_dpo = DPO_INVALID; - - /* - * interpose a policy DPO from the endpoint so that policy - * is applied - */ - gbp_policy_dpo_add_or_lock (fib_proto_to_dpo (pfx->fp_proto), - grd->grd_scope, - gg->gg_sclass, ~0, &policy_dpo); - - fib_table_entry_special_dpo_add (fib_index, pfx, - gbp_fib_source_hi, - FIB_ENTRY_FLAG_INTERPOSE, - &policy_dpo); - dpo_reset (&policy_dpo); - } - - /* - * send a gratuitous ARP on the EPG's uplink. this is done so - * that if this EP has moved from some other place in the - * 'fabric', upstream devices are informed - */ - if (gbp_endpoint_is_local (ge) && ~0 != gg->gg_uplink_sw_if_index) - { - gbp_endpoint_add_itf (gbp_itf_get_sw_if_index (gef->gef_itf), - gei); - if (FIB_PROTOCOL_IP4 == pfx->fp_proto) - ip4_neighbor_advertise (vlib_get_main (), - vnet_get_main (), - gg->gg_uplink_sw_if_index, - &pfx->fp_addr.ip4); - else - ip6_neighbor_advertise (vlib_get_main (), - vnet_get_main (), - gg->gg_uplink_sw_if_index, - &pfx->fp_addr.ip6); - } - } - } - - if (gbp_endpoint_is_external (ge)) - { - gbp_itf_l2_set_input_feature (gef->gef_itf, - L2INPUT_FEAT_GBP_LPM_CLASSIFY); - } - else if (gbp_endpoint_is_local (ge)) - { - /* - * non-remote endpoints (i.e. those not arriving on iVXLAN - * tunnels) need to be classifed based on the the input interface. - * We enable the GBP-FWD feature only if the group has an uplink - * interface (on which the GBP-FWD feature would send UU traffic). - * External endpoints get classified based on an LPM match - */ - l2input_feat_masks_t feats = L2INPUT_FEAT_GBP_SRC_CLASSIFY; - - if (NULL != gg && ~0 != gg->gg_uplink_sw_if_index) - feats |= L2INPUT_FEAT_GBP_FWD; - gbp_itf_l2_set_input_feature (gef->gef_itf, feats); - } - - /* - * update children with the new forwarding info - */ - fib_node_back_walk_ctx_t bw_ctx = { - .fnbw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE, - .fnbw_flags = FIB_NODE_BW_FLAG_FORCE_SYNC, - }; - - fib_walk_sync (gbp_endpoint_fib_type, gei, &bw_ctx); -} - -int -gbp_endpoint_update_and_lock (gbp_endpoint_src_t src, - u32 sw_if_index, - const ip46_address_t * ips, - const mac_address_t * mac, - index_t gbdi, index_t grdi, - sclass_t sclass, - gbp_endpoint_flags_t flags, - const ip46_address_t * tun_src, - const ip46_address_t * tun_dst, u32 * handle) -{ - gbp_bridge_domain_t *gbd; - gbp_endpoint_group_t *gg; - gbp_endpoint_src_t best; - gbp_route_domain_t *grd; - gbp_endpoint_loc_t *gel; - gbp_endpoint_t *ge; - index_t ggi, gei; - int rv; - - if (~0 == sw_if_index) - return (VNET_API_ERROR_INVALID_SW_IF_INDEX); - - ge = NULL; - gg = NULL; - - /* - * we need to determine the bridge-domain, either from the EPG or - * the BD passed - */ - if (SCLASS_INVALID != sclass) - { - ggi = gbp_endpoint_group_find (sclass); - - if (INDEX_INVALID == ggi) - return (VNET_API_ERROR_NO_SUCH_ENTRY); - - gg = gbp_endpoint_group_get (ggi); - gbdi = gg->gg_gbd; - grdi = gg->gg_rd; - } - else - { - if (INDEX_INVALID == gbdi) - return (VNET_API_ERROR_NO_SUCH_ENTRY); - if (INDEX_INVALID == grdi) - return (VNET_API_ERROR_NO_SUCH_FIB); - ggi = INDEX_INVALID; - } - - gbd = gbp_bridge_domain_get (gbdi); - grd = gbp_route_domain_get (grdi); - rv = gbp_endpoint_find_for_update (ips, grd, mac, gbd, &ge); - - if (0 != rv) - return (rv); - - if (NULL == ge) - { - ge = gbp_endpoint_alloc (ips, grd, mac, gbd); - } - else - { - gbp_endpoint_ips_update (ge, ips, grd); - } - - best = gbp_endpoint_get_best_src (ge); - gei = gbp_endpoint_index (ge); - gel = gbp_endpoint_loc_find_or_add (ge, src); - - gbp_endpoint_loc_update (ge, gel, gbd, sw_if_index, ggi, flags, - tun_src, tun_dst); - - if (src <= best) - { - /* - * either the best source has been updated or we have a new best source - */ - gbb_endpoint_fwd_reset (ge); - gbb_endpoint_fwd_recalc (ge); - } - else - { - /* - * an update to a lower priority source, so we need do nothing - */ - } - - if (handle) - *handle = gei; - - GBP_ENDPOINT_INFO ("update: %U", format_gbp_endpoint, gei); - - return (0); -} - -void -gbp_endpoint_unlock (gbp_endpoint_src_t src, index_t gei) -{ - gbp_endpoint_loc_t *gel, gel_copy; - gbp_endpoint_src_t best; - gbp_endpoint_t *ge; - int removed; - - if (pool_is_free_index (gbp_endpoint_pool, gei)) - return; - - GBP_ENDPOINT_INFO ("delete: %U", format_gbp_endpoint, gei); - - ge = gbp_endpoint_get (gei); - - gel = gbp_endpoint_loc_find (ge, src); - - if (NULL == gel) - return; - - /* - * lock the EP so we can control when it is deleted - */ - fib_node_lock (&ge->ge_node); - best = gbp_endpoint_get_best_src (ge); - - /* - * copy the location info since we'll lose it when it's removed from - * the vector - */ - clib_memcpy (&gel_copy, gel, sizeof (gel_copy)); - - /* - * remove the source we no longer need - */ - removed = gbp_endpoint_loc_unlock (ge, gel); - - if (src == best) - { - /* - * we have removed the old best source => recalculate fwding - */ - if (0 == vec_len (ge->ge_locs)) - { - /* - * if there are no more sources left, then we need only release - * the fwding resources held and then this EP is gawn. - */ - gbb_endpoint_fwd_reset (ge); - } - else - { - /* - * else there are more sources. release the old and get new - * fwding objects - */ - gbb_endpoint_fwd_reset (ge); - gbb_endpoint_fwd_recalc (ge); - } - } - /* - * else - * we removed a lower priority source so we need to do nothing - */ - - /* - * clear up any resources held by the source - */ - if (removed) - gbp_endpoint_loc_destroy (&gel_copy); - - /* - * remove the lock taken above - */ - fib_node_unlock (&ge->ge_node); - /* - * We may have removed the last source and so this EP is now TOAST - * DO NOTHING BELOW HERE - */ -} - -u32 -gbp_endpoint_child_add (index_t gei, - fib_node_type_t type, fib_node_index_t index) -{ - return (fib_node_child_add (gbp_endpoint_fib_type, gei, type, index)); -} - -void -gbp_endpoint_child_remove (index_t gei, u32 sibling) -{ - return (fib_node_child_remove (gbp_endpoint_fib_type, gei, sibling)); -} - -typedef struct gbp_endpoint_flush_ctx_t_ -{ - u32 sw_if_index; - gbp_endpoint_src_t src; - index_t *geis; -} gbp_endpoint_flush_ctx_t; - -static walk_rc_t -gbp_endpoint_flush_cb (index_t gei, void *args) -{ - gbp_endpoint_flush_ctx_t *ctx = args; - gbp_endpoint_loc_t *gel; - gbp_endpoint_t *ge; - - ge = gbp_endpoint_get (gei); - gel = gbp_endpoint_loc_find (ge, ctx->src); - - if ((NULL != gel) && ctx->sw_if_index == gel->tun.gel_parent_sw_if_index) - { - vec_add1 (ctx->geis, gei); - } - - return (WALK_CONTINUE); -} - -/** - * remove all learnt endpoints using the interface - */ -void -gbp_endpoint_flush (gbp_endpoint_src_t src, u32 sw_if_index) -{ - gbp_endpoint_flush_ctx_t ctx = { - .sw_if_index = sw_if_index, - .src = src, - }; - index_t *gei; - - GBP_ENDPOINT_INFO ("flush: %U %U", - format_gbp_endpoint_src, src, - format_vnet_sw_if_index_name, vnet_get_main (), - sw_if_index); - gbp_endpoint_walk (gbp_endpoint_flush_cb, &ctx); - - vec_foreach (gei, ctx.geis) - { - gbp_endpoint_unlock (src, *gei); - } - - vec_free (ctx.geis); -} - -void -gbp_endpoint_walk (gbp_endpoint_cb_t cb, void *ctx) -{ - u32 index; - - /* *INDENT-OFF* */ - pool_foreach_index (index, gbp_endpoint_pool) - { - if (!cb(index, ctx)) - break; - } - /* *INDENT-ON* */ -} - -static clib_error_t * -gbp_endpoint_cli (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - ip46_address_t ip = ip46_address_initializer, *ips = NULL; - mac_address_t mac = ZERO_MAC_ADDRESS; - vnet_main_t *vnm = vnet_get_main (); - u32 sclass = SCLASS_INVALID; - u32 handle = INDEX_INVALID; - u32 sw_if_index = ~0; - u32 flags = GBP_ENDPOINT_FLAG_NONE; - u8 add = 1; - int rv; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - ip46_address_reset (&ip); - - if (unformat (input, "%U", unformat_vnet_sw_interface, - vnm, &sw_if_index)) - ; - else if (unformat (input, "add")) - add = 1; - else if (unformat (input, "del")) - add = 0; - else if (unformat (input, "sclass %d", &sclass)) - ; - else if (unformat (input, "handle %d", &handle)) - ; - else if (unformat (input, "ip %U", unformat_ip4_address, &ip.ip4)) - vec_add1 (ips, ip); - else if (unformat (input, "ip %U", unformat_ip6_address, &ip.ip6)) - vec_add1 (ips, ip); - else if (unformat (input, "mac %U", unformat_mac_address, &mac)) - ; - else if (unformat (input, "flags 0x%x", &flags)) - ; - else - break; - } - - if (add) - { - if (~0 == sw_if_index) - return clib_error_return (0, "interface must be specified"); - if (SCLASS_INVALID == sclass) - return clib_error_return (0, "SCLASS must be specified"); - - rv = - gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_CP, - sw_if_index, ips, &mac, - INDEX_INVALID, INDEX_INVALID, - sclass, flags, NULL, NULL, &handle); - - if (rv) - return clib_error_return (0, "GBP Endpoint update returned %d", rv); - else - vlib_cli_output (vm, "handle %d\n", handle); - } - else - { - if (INDEX_INVALID == handle) - return clib_error_return (0, "handle must be specified"); - - gbp_endpoint_unlock (GBP_ENDPOINT_SRC_CP, handle); - } - - vec_free (ips); - - return (NULL); -} - -/*? - * Configure a GBP Endpoint - * - * @cliexpar - * @cliexstart{gbp endpoint del <handle> | [add] <interface> sclass <SCLASS> ip <IP> mac <MAC> [flags <flags>]} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_endpoint_cli_node, static) = { - .path = "gbp endpoint", - .short_help = "gbp endpoint del <handle> | [add] <interface> sclass <SCLASS> ip <IP> mac <MAC> [flags <flags>]", - .function = gbp_endpoint_cli, -}; -/* *INDENT-ON* */ - -u8 * -format_gbp_endpoint_src (u8 * s, va_list * args) -{ - gbp_endpoint_src_t action = va_arg (*args, gbp_endpoint_src_t); - - switch (action) - { -#define _(v,a) case GBP_ENDPOINT_SRC_##v: return (format (s, "%s", a)); - foreach_gbp_endpoint_src -#undef _ - } - - return (format (s, "unknown")); -} - -static u8 * -format_gbp_endpoint_fwd (u8 * s, va_list * args) -{ - gbp_endpoint_fwd_t *gef = va_arg (*args, gbp_endpoint_fwd_t *); - - s = format (s, "fwd:"); - s = format (s, "\n itf:[%U]", format_gbp_itf_hdl, gef->gef_itf); - if (GBP_ENDPOINT_FLAG_NONE != gef->gef_flags) - { - s = format (s, " flags:%U", format_gbp_endpoint_flags, gef->gef_flags); - } - - return (s); -} - -static u8 * -format_gbp_endpoint_key (u8 * s, va_list * args) -{ - gbp_endpoint_key_t *gek = va_arg (*args, gbp_endpoint_key_t *); - const fib_prefix_t *pfx; - - s = format (s, "ips:["); - - vec_foreach (pfx, gek->gek_ips) - { - s = format (s, "%U, ", format_fib_prefix, pfx); - } - s = format (s, "]"); - - s = format (s, " mac:%U", format_mac_address_t, &gek->gek_mac); - - return (s); -} - -static u8 * -format_gbp_endpoint_loc (u8 * s, va_list * args) -{ - gbp_endpoint_loc_t *gel = va_arg (*args, gbp_endpoint_loc_t *); - - s = format (s, "%U", format_gbp_endpoint_src, gel->gel_src); - s = format (s, "\n EPG:%d [%U]", gel->gel_epg, - format_gbp_itf_hdl, gel->gel_itf); - - if (GBP_ENDPOINT_FLAG_NONE != gel->gel_flags) - { - s = format (s, " flags:%U", format_gbp_endpoint_flags, gel->gel_flags); - } - if (GBP_ENDPOINT_FLAG_REMOTE & gel->gel_flags) - { - s = format (s, " tun:["); - s = format (s, "parent:%U", format_vnet_sw_if_index_name, - vnet_get_main (), gel->tun.gel_parent_sw_if_index); - s = format (s, " {%U,%U}]", - format_ip46_address, &gel->tun.gel_src, IP46_TYPE_ANY, - format_ip46_address, &gel->tun.gel_dst, IP46_TYPE_ANY); - } - - return (s); -} - -u8 * -format_gbp_endpoint (u8 * s, va_list * args) -{ - index_t gei = va_arg (*args, index_t); - gbp_endpoint_loc_t *gel; - gbp_endpoint_t *ge; - - ge = gbp_endpoint_get (gei); - - s = format (s, "[@%d] %U", gei, format_gbp_endpoint_key, &ge->ge_key); - s = format (s, " last-time:[%f]", ge->ge_last_time); - - vec_foreach (gel, ge->ge_locs) - { - s = format (s, "\n %U", format_gbp_endpoint_loc, gel); - } - s = format (s, "\n %U", format_gbp_endpoint_fwd, &ge->ge_fwd); - - return s; -} - -static walk_rc_t -gbp_endpoint_show_one (index_t gei, void *ctx) -{ - vlib_main_t *vm; - - vm = ctx; - vlib_cli_output (vm, " %U", format_gbp_endpoint, gei); - - return (WALK_CONTINUE); -} - -static int -gbp_endpoint_walk_ip_itf (clib_bihash_kv_24_8_t * kvp, void *arg) -{ - ip46_address_t ip; - vlib_main_t *vm; - u32 sw_if_index; - - vm = arg; - - gbp_endpoint_extract_key_ip_itf (kvp, &ip, &sw_if_index); - - vlib_cli_output (vm, " {%U, %U} -> %d", - format_ip46_address, &ip, IP46_TYPE_ANY, - format_vnet_sw_if_index_name, vnet_get_main (), - sw_if_index, kvp->value); - return (BIHASH_WALK_CONTINUE); -} - -static int -gbp_endpoint_walk_mac_itf (clib_bihash_kv_16_8_t * kvp, void *arg) -{ - mac_address_t mac; - vlib_main_t *vm; - u32 sw_if_index; - - vm = arg; - - gbp_endpoint_extract_key_mac_itf (kvp, &mac, &sw_if_index); - - vlib_cli_output (vm, " {%U, %U} -> %d", - format_mac_address_t, &mac, - format_vnet_sw_if_index_name, vnet_get_main (), - sw_if_index, kvp->value); - return (BIHASH_WALK_CONTINUE); -} - -static clib_error_t * -gbp_endpoint_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - u32 show_dbs, handle; - - handle = INDEX_INVALID; - show_dbs = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "%d", &handle)) - ; - else if (unformat (input, "db")) - show_dbs = 1; - else - break; - } - - if (INDEX_INVALID != handle) - { - vlib_cli_output (vm, "%U", format_gbp_endpoint, handle); - } - else if (show_dbs) - { - vlib_cli_output (vm, "\nDatabases:"); - clib_bihash_foreach_key_value_pair_24_8 (&gbp_ep_db.ged_by_ip_rd, - gbp_endpoint_walk_ip_itf, vm); - clib_bihash_foreach_key_value_pair_16_8 - (&gbp_ep_db.ged_by_mac_bd, gbp_endpoint_walk_mac_itf, vm); - } - else - { - vlib_cli_output (vm, "Endpoints:"); - gbp_endpoint_walk (gbp_endpoint_show_one, vm); - } - - return (NULL); -} - -/*? - * Show Group Based Policy Endpoints and derived information - * - * @cliexpar - * @cliexstart{show gbp endpoint} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_endpoint_show_node, static) = { - .path = "show gbp endpoint", - .short_help = "show gbp endpoint\n", - .function = gbp_endpoint_show, -}; -/* *INDENT-ON* */ - -static void -gbp_endpoint_check (index_t gei, f64 start_time) -{ - gbp_endpoint_group_t *gg; - gbp_endpoint_loc_t *gel; - gbp_endpoint_t *ge; - - ge = gbp_endpoint_get (gei); - gel = gbp_endpoint_loc_find (ge, GBP_ENDPOINT_SRC_DP); - - if (NULL != gel) - { - gg = gbp_endpoint_group_get (gel->gel_epg); - - if ((start_time - ge->ge_last_time) > - gg->gg_retention.remote_ep_timeout) - { - gbp_endpoint_unlock (GBP_ENDPOINT_SRC_DP, gei); - } - } -} - -static void -gbp_endpoint_scan_l2 (vlib_main_t * vm) -{ - clib_bihash_16_8_t *gte_table = &gbp_ep_db.ged_by_mac_bd; - f64 last_start, start_time, delta_t; - int i, j, k; - - if (!gte_table->instantiated) - return; - - delta_t = 0; - last_start = start_time = vlib_time_now (vm); - - for (i = 0; i < gte_table->nbuckets; i++) - { - clib_bihash_bucket_16_8_t *b; - clib_bihash_value_16_8_t *v; - - /* allow no more than 20us without a pause */ - delta_t = vlib_time_now (vm) - last_start; - if (delta_t > 20e-6) - { - /* suspend for 100 us */ - vlib_process_suspend (vm, 100e-6); - last_start = vlib_time_now (vm); - } - - b = clib_bihash_get_bucket_16_8 (gte_table, i); - if (clib_bihash_bucket_is_empty_16_8 (b)) - continue; - v = clib_bihash_get_value_16_8 (gte_table, b->offset); - - for (j = 0; j < (1 << b->log2_pages); j++) - { - for (k = 0; k < BIHASH_KVP_PER_PAGE; k++) - { - if (clib_bihash_is_free_16_8 (&v->kvp[k])) - continue; - - gbp_endpoint_check (v->kvp[k].value, start_time); - - /* - * Note: we may have just freed the bucket's backing - * storage, so check right here... - */ - if (clib_bihash_bucket_is_empty_16_8 (b)) - goto doublebreak; - } - v++; - } - doublebreak: - ; - } -} - -static void -gbp_endpoint_scan_l3 (vlib_main_t * vm) -{ - clib_bihash_24_8_t *gte_table = &gbp_ep_db.ged_by_ip_rd; - f64 last_start, start_time, delta_t; - int i, j, k; - - if (!gte_table->instantiated) - return; - - delta_t = 0; - last_start = start_time = vlib_time_now (vm); - - for (i = 0; i < gte_table->nbuckets; i++) - { - clib_bihash_bucket_24_8_t *b; - clib_bihash_value_24_8_t *v; - - /* allow no more than 20us without a pause */ - delta_t = vlib_time_now (vm) - last_start; - if (delta_t > 20e-6) - { - /* suspend for 100 us */ - vlib_process_suspend (vm, 100e-6); - last_start = vlib_time_now (vm); - } - - b = clib_bihash_get_bucket_24_8 (gte_table, i); - if (clib_bihash_bucket_is_empty_24_8 (b)) - continue; - v = clib_bihash_get_value_24_8 (gte_table, b->offset); - - for (j = 0; j < (1 << b->log2_pages); j++) - { - for (k = 0; k < BIHASH_KVP_PER_PAGE; k++) - { - if (clib_bihash_is_free_24_8 (&v->kvp[k])) - continue; - - gbp_endpoint_check (v->kvp[k].value, start_time); - - /* - * Note: we may have just freed the bucket's backing - * storage, so check right here... - */ - if (clib_bihash_bucket_is_empty_24_8 (b)) - goto doublebreak; - } - v++; - } - doublebreak: - ; - } -} - -void -gbp_endpoint_scan (vlib_main_t * vm) -{ - gbp_endpoint_scan_l2 (vm); - gbp_endpoint_scan_l3 (vm); -} - -static fib_node_t * -gbp_endpoint_get_node (fib_node_index_t index) -{ - gbp_endpoint_t *ge; - - ge = gbp_endpoint_get (index); - - return (&ge->ge_node); -} - -static gbp_endpoint_t * -gbp_endpoint_from_fib_node (fib_node_t * node) -{ - ASSERT (gbp_endpoint_fib_type == node->fn_type); - return ((gbp_endpoint_t *) node); -} - -static void -gbp_endpoint_last_lock_gone (fib_node_t * node) -{ - const gbp_bridge_domain_t *gbd; - const gbp_route_domain_t *grd; - const fib_prefix_t *pfx; - gbp_endpoint_t *ge; - - ge = gbp_endpoint_from_fib_node (node); - - ASSERT (0 == vec_len (ge->ge_locs)); - - gbd = gbp_bridge_domain_get (ge->ge_key.gek_gbd); - - /* - * we have removed the last source. this EP is toast - */ - if (INDEX_INVALID != ge->ge_key.gek_gbd) - { - gbp_endpoint_del_mac (&ge->ge_key.gek_mac, gbd->gb_bd_index); - } - vec_foreach (pfx, ge->ge_key.gek_ips) - { - grd = gbp_route_domain_get (ge->ge_key.gek_grd); - gbp_endpoint_del_ip (&pfx->fp_addr, grd->grd_fib_index[pfx->fp_proto]); - } - pool_put (gbp_endpoint_pool, ge); -} - -static fib_node_back_walk_rc_t -gbp_endpoint_back_walk_notify (fib_node_t * node, - fib_node_back_walk_ctx_t * ctx) -{ - ASSERT (0); - - return (FIB_NODE_BACK_WALK_CONTINUE); -} - -/* - * The FIB path's graph node virtual function table - */ -static const fib_node_vft_t gbp_endpoint_vft = { - .fnv_get = gbp_endpoint_get_node, - .fnv_last_lock = gbp_endpoint_last_lock_gone, - .fnv_back_walk = gbp_endpoint_back_walk_notify, - // .fnv_mem_show = fib_path_memory_show, -}; - -static clib_error_t * -gbp_endpoint_init (vlib_main_t * vm) -{ -#define GBP_EP_HASH_NUM_BUCKETS (2 * 1024) -#define GBP_EP_HASH_MEMORY_SIZE (1 << 20) - - clib_bihash_init_24_8 (&gbp_ep_db.ged_by_ip_rd, - "GBP Endpoints - IP/RD", - GBP_EP_HASH_NUM_BUCKETS, GBP_EP_HASH_MEMORY_SIZE); - - clib_bihash_init_16_8 (&gbp_ep_db.ged_by_mac_bd, - "GBP Endpoints - MAC/BD", - GBP_EP_HASH_NUM_BUCKETS, GBP_EP_HASH_MEMORY_SIZE); - - gbp_ep_logger = vlib_log_register_class ("gbp", "ep"); - gbp_endpoint_fib_type = fib_node_register_new_type (&gbp_endpoint_vft); - gbp_fib_source_hi = fib_source_allocate ("gbp-endpoint-hi", - FIB_SOURCE_PRIORITY_HI, - FIB_SOURCE_BH_SIMPLE); - gbp_fib_source_low = fib_source_allocate ("gbp-endpoint-low", - FIB_SOURCE_PRIORITY_LOW, - FIB_SOURCE_BH_SIMPLE); - - return (NULL); -} - -VLIB_INIT_FUNCTION (gbp_endpoint_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_endpoint.h b/src/plugins/gbp/gbp_endpoint.h deleted file mode 100644 index 3155e7be4e0..00000000000 --- a/src/plugins/gbp/gbp_endpoint.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_ENDPOINT_H__ -#define __GBP_ENDPOINT_H__ - -#include <plugins/gbp/gbp_types.h> -#include <plugins/gbp/gbp_itf.h> -#include <vnet/ip/ip.h> -#include <vnet/ethernet/mac_address.h> - -#include <vppinfra/bihash_16_8.h> -#include <vppinfra/bihash_template.h> -#include <vppinfra/bihash_24_8.h> -#include <vppinfra/bihash_template.h> - -/** - * Flags for each endpoint - */ -typedef enum gbp_endpoint_attr_t_ -{ - GBP_ENDPOINT_ATTR_FIRST = 0, - GBP_ENDPOINT_ATTR_BOUNCE = GBP_ENDPOINT_ATTR_FIRST, - GBP_ENDPOINT_ATTR_REMOTE, - GBP_ENDPOINT_ATTR_LEARNT, - GBP_ENDPOINT_ATTR_EXTERNAL, - GBP_ENDPOINT_ATTR_LAST, -} gbp_endpoint_attr_t; - -typedef enum gbp_endpoint_flags_t_ -{ - GBP_ENDPOINT_FLAG_NONE = 0, - GBP_ENDPOINT_FLAG_BOUNCE = (1 << GBP_ENDPOINT_ATTR_BOUNCE), - GBP_ENDPOINT_FLAG_REMOTE = (1 << GBP_ENDPOINT_ATTR_REMOTE), - GBP_ENDPOINT_FLAG_LEARNT = (1 << GBP_ENDPOINT_ATTR_LEARNT), - GBP_ENDPOINT_FLAG_EXTERNAL = (1 << GBP_ENDPOINT_ATTR_EXTERNAL), -} gbp_endpoint_flags_t; - -#define GBP_ENDPOINT_ATTR_NAMES { \ - [GBP_ENDPOINT_ATTR_BOUNCE] = "bounce", \ - [GBP_ENDPOINT_ATTR_REMOTE] = "remote", \ - [GBP_ENDPOINT_ATTR_LEARNT] = "learnt", \ - [GBP_ENDPOINT_ATTR_EXTERNAL] = "external", \ -} - -extern u8 *format_gbp_endpoint_flags (u8 * s, va_list * args); - -/** - * Sources of Endpoints in priority order. The best (lowest value) source - * provides the forwarding information. - * Data-plane takes preference because the CP data is not always complete, - * it may not have the sclass. - */ -#define foreach_gbp_endpoint_src \ - _(DP, "data-plane") \ - _(CP, "control-plane") \ - _(RR, "recursive-resolution") - -typedef enum gbp_endpoint_src_t_ -{ -#define _(v,s) GBP_ENDPOINT_SRC_##v, - foreach_gbp_endpoint_src -#undef _ -} gbp_endpoint_src_t; - -#define GBP_ENDPOINT_SRC_MAX (GBP_ENDPOINT_SRC_RR+1) - -extern u8 *format_gbp_endpoint_src (u8 * s, va_list * args); - -/** - * This is the identity of an endpoint, as such it is information - * about an endpoint that is idempotent. - * The ID is used to add the EP into the various data-bases for retrieval. - */ -typedef struct gbp_endpoint_key_t_ -{ - /** - * A vector of ip addresses that belong to the endpoint. - * Together with the route EPG's RD this forms the EP's L3 key - */ - fib_prefix_t *gek_ips; - - /** - * MAC address of the endpoint. - * Together with the route EPG's BD this forms the EP's L2 key - */ - mac_address_t gek_mac; - - /** - * Index of the Bridge-Domain - */ - index_t gek_gbd; - - /** - * Index of the Route-Domain - */ - index_t gek_grd; -} gbp_endpoint_key_t; - -/** - * Information about the location of the endpoint provided by a source - * of endpoints - */ -typedef struct gbp_endpoint_loc_t_ -{ - /** - * The source providing this location information - */ - gbp_endpoint_src_t gel_src; - - /** - * The interface on which the EP is connected - */ - gbp_itf_hdl_t gel_itf; - - /** - * Endpoint flags - */ - gbp_endpoint_flags_t gel_flags; - - /** - * Endpoint Group. - */ - index_t gel_epg; - - /** - * number of times this source has locked this - */ - u32 gel_locks; - - /** - * Tunnel info for remote endpoints - */ - struct - { - u32 gel_parent_sw_if_index; - ip46_address_t gel_src; - ip46_address_t gel_dst; - } tun; -} gbp_endpoint_loc_t; - -/** - * And endpoints current forwarding state - */ -typedef struct gbp_endpoint_fwd_t_ -{ - /** - * The interface on which the EP is connected - */ - gbp_itf_hdl_t gef_itf; - - /** - * The L3 adj, if created - */ - index_t *gef_adjs; - - /** - * Endpoint Group's sclass. cached for fast DP access. - */ - sclass_t gef_sclass; - - /** - * FIB index the EP is in - */ - u32 gef_fib_index; - - gbp_endpoint_flags_t gef_flags; -} gbp_endpoint_fwd_t; - -/** - * A Group Based Policy Endpoint. - * This is typically a VM or container. If the endpoint is local (i.e. on - * the same compute node as VPP) then there is one interface per-endpoint. - * If the EP is remote,e.g. reachable over a [vxlan] tunnel, then there - * will be multiple EPs reachable over the tunnel and they can be distinguished - * via either their MAC or IP Address[es]. - */ -typedef struct gbp_endpoint_t_ -{ - /** - * A FIB node that allows the tracking of children. - */ - fib_node_t ge_node; - - /** - * The key/ID of this EP - */ - gbp_endpoint_key_t ge_key; - - /** - * Location information provided by the various sources. - * These are sorted based on source priority. - */ - gbp_endpoint_loc_t *ge_locs; - - gbp_endpoint_fwd_t ge_fwd; - - /** - * The last time a packet from seen from this end point - */ - f64 ge_last_time; -} gbp_endpoint_t; - -extern u8 *format_gbp_endpoint (u8 * s, va_list * args); - -/** - * GBP Endpoint Databases - */ -typedef struct gbp_ep_by_ip_itf_db_t_ -{ - index_t *ged_by_sw_if_index; - clib_bihash_24_8_t ged_by_ip_rd; - clib_bihash_16_8_t ged_by_mac_bd; -} gbp_ep_db_t; - -extern int gbp_endpoint_update_and_lock (gbp_endpoint_src_t src, - u32 sw_if_index, - const ip46_address_t * ip, - const mac_address_t * mac, - index_t gbd, index_t grd, - sclass_t sclass, - gbp_endpoint_flags_t flags, - const ip46_address_t * tun_src, - const ip46_address_t * tun_dst, - u32 * handle); -extern void gbp_endpoint_unlock (gbp_endpoint_src_t src, index_t gbpei); -extern u32 gbp_endpoint_child_add (index_t gei, - fib_node_type_t type, - fib_node_index_t index); -extern void gbp_endpoint_child_remove (index_t gei, u32 sibling); - -typedef walk_rc_t (*gbp_endpoint_cb_t) (index_t gbpei, void *ctx); -extern void gbp_endpoint_walk (gbp_endpoint_cb_t cb, void *ctx); -extern void gbp_endpoint_scan (vlib_main_t * vm); -extern int gbp_endpoint_is_remote (const gbp_endpoint_t * ge); -extern int gbp_endpoint_is_local (const gbp_endpoint_t * ge); -extern int gbp_endpoint_is_external (const gbp_endpoint_t * ge); -extern int gbp_endpoint_is_learnt (const gbp_endpoint_t * ge); - - -extern void gbp_endpoint_flush (gbp_endpoint_src_t src, u32 sw_if_index); - -/** - * DP functions and databases - */ -extern gbp_ep_db_t gbp_ep_db; -extern gbp_endpoint_t *gbp_endpoint_pool; - -/** - * Get the endpoint from a port/interface - */ -always_inline gbp_endpoint_t * -gbp_endpoint_get (index_t gbpei) -{ - return (pool_elt_at_index (gbp_endpoint_pool, gbpei)); -} - -static_always_inline void -gbp_endpoint_mk_key_mac (const u8 * mac, - u32 bd_index, clib_bihash_kv_16_8_t * key) -{ - key->key[0] = ethernet_mac_address_u64 (mac); - key->key[1] = bd_index; -} - -static_always_inline gbp_endpoint_t * -gbp_endpoint_find_mac (const u8 * mac, u32 bd_index) -{ - clib_bihash_kv_16_8_t key, value; - int rv; - - gbp_endpoint_mk_key_mac (mac, bd_index, &key); - - rv = clib_bihash_search_16_8 (&gbp_ep_db.ged_by_mac_bd, &key, &value); - - if (0 != rv) - return NULL; - - return (gbp_endpoint_get (value.value)); -} - -static_always_inline void -gbp_endpoint_mk_key_ip (const ip46_address_t * ip, - u32 fib_index, clib_bihash_kv_24_8_t * key) -{ - key->key[0] = ip->as_u64[0]; - key->key[1] = ip->as_u64[1]; - key->key[2] = fib_index; -} - -static_always_inline void -gbp_endpoint_mk_key_ip4 (const ip4_address_t * ip, - u32 fib_index, clib_bihash_kv_24_8_t * key) -{ - const ip46_address_t a = { - .ip4 = *ip, - }; - gbp_endpoint_mk_key_ip (&a, fib_index, key); -} - -static_always_inline gbp_endpoint_t * -gbp_endpoint_find_ip4 (const ip4_address_t * ip, u32 fib_index) -{ - clib_bihash_kv_24_8_t key, value; - int rv; - - gbp_endpoint_mk_key_ip4 (ip, fib_index, &key); - - rv = clib_bihash_search_24_8 (&gbp_ep_db.ged_by_ip_rd, &key, &value); - - if (0 != rv) - return NULL; - - return (gbp_endpoint_get (value.value)); -} - -static_always_inline void -gbp_endpoint_mk_key_ip6 (const ip6_address_t * ip, - u32 fib_index, clib_bihash_kv_24_8_t * key) -{ - key->key[0] = ip->as_u64[0]; - key->key[1] = ip->as_u64[1]; - key->key[2] = fib_index; -} - -static_always_inline gbp_endpoint_t * -gbp_endpoint_find_ip6 (const ip6_address_t * ip, u32 fib_index) -{ - clib_bihash_kv_24_8_t key, value; - int rv; - - gbp_endpoint_mk_key_ip6 (ip, fib_index, &key); - - rv = clib_bihash_search_24_8 (&gbp_ep_db.ged_by_ip_rd, &key, &value); - - if (0 != rv) - return NULL; - - return (gbp_endpoint_get (value.value)); -} - -static_always_inline gbp_endpoint_t * -gbp_endpoint_find_itf (u32 sw_if_index) -{ - index_t gei; - - gei = gbp_ep_db.ged_by_sw_if_index[sw_if_index]; - - if (INDEX_INVALID != gei) - return (gbp_endpoint_get (gei)); - - return (NULL); -} - - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_endpoint_group.c b/src/plugins/gbp/gbp_endpoint_group.c deleted file mode 100644 index b9044378e3b..00000000000 --- a/src/plugins/gbp/gbp_endpoint_group.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * gbp.h : Group Based Policy - * - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp_endpoint_group.h> -#include <plugins/gbp/gbp_endpoint.h> -#include <plugins/gbp/gbp_bridge_domain.h> -#include <plugins/gbp/gbp_route_domain.h> -#include <plugins/gbp/gbp_itf.h> - -#include <vnet/dpo/dvr_dpo.h> -#include <vnet/fib/fib_table.h> -#include <vnet/l2/l2_input.h> - -/** - * Pool of GBP endpoint_groups - */ -gbp_endpoint_group_t *gbp_endpoint_group_pool; - -/** - * DB of endpoint_groups - */ -gbp_endpoint_group_db_t gbp_endpoint_group_db; - -/** - * Map sclass to EPG - */ -uword *gbp_epg_sclass_db; - -vlib_log_class_t gg_logger; - -#define GBP_EPG_DBG(...) \ - vlib_log_debug (gg_logger, __VA_ARGS__); - -gbp_endpoint_group_t * -gbp_endpoint_group_get (index_t i) -{ - return (pool_elt_at_index (gbp_endpoint_group_pool, i)); -} - -void -gbp_endpoint_group_lock (index_t ggi) -{ - gbp_endpoint_group_t *gg; - - if (INDEX_INVALID == ggi) - return; - - gg = gbp_endpoint_group_get (ggi); - gg->gg_locks++; -} - -index_t -gbp_endpoint_group_find (sclass_t sclass) -{ - uword *p; - - p = hash_get (gbp_endpoint_group_db.gg_hash_sclass, sclass); - - if (NULL != p) - return p[0]; - - return (INDEX_INVALID); -} - -int -gbp_endpoint_group_add_and_lock (vnid_t vnid, - u16 sclass, - u32 bd_id, - u32 rd_id, - u32 uplink_sw_if_index, - const gbp_endpoint_retention_t * retention) -{ - gbp_endpoint_group_t *gg; - index_t ggi; - - ggi = gbp_endpoint_group_find (sclass); - - if (INDEX_INVALID == ggi) - { - fib_protocol_t fproto; - index_t gbi, grdi; - - gbi = gbp_bridge_domain_find_and_lock (bd_id); - - if (~0 == gbi) - return (VNET_API_ERROR_BD_NOT_MODIFIABLE); - - grdi = gbp_route_domain_find_and_lock (rd_id); - - if (~0 == grdi) - { - gbp_bridge_domain_unlock (gbi); - return (VNET_API_ERROR_NO_SUCH_FIB); - } - - pool_get_zero (gbp_endpoint_group_pool, gg); - - gg->gg_vnid = vnid; - gg->gg_rd = grdi; - gg->gg_gbd = gbi; - - gg->gg_uplink_sw_if_index = uplink_sw_if_index; - gbp_itf_hdl_reset (&gg->gg_uplink_itf); - gg->gg_locks = 1; - gg->gg_sclass = sclass; - gg->gg_retention = *retention; - - if (SCLASS_INVALID != gg->gg_sclass) - hash_set (gbp_epg_sclass_db, gg->gg_sclass, gg->gg_vnid); - - /* - * an egress DVR dpo for internal subnets to use when sending - * on the uplink interface - */ - if (~0 != gg->gg_uplink_sw_if_index) - { - FOR_EACH_FIB_IP_PROTOCOL (fproto) - { - dvr_dpo_add_or_lock (uplink_sw_if_index, - fib_proto_to_dpo (fproto), - &gg->gg_dpo[fproto]); - } - - /* - * Add the uplink to the BD - * packets direct from the uplink have had policy applied - */ - gg->gg_uplink_itf = - gbp_itf_l2_add_and_lock (gg->gg_uplink_sw_if_index, gbi); - - gbp_itf_l2_set_input_feature (gg->gg_uplink_itf, - L2INPUT_FEAT_GBP_NULL_CLASSIFY); - } - - hash_set (gbp_endpoint_group_db.gg_hash_sclass, - gg->gg_sclass, gg - gbp_endpoint_group_pool); - } - else - { - gg = gbp_endpoint_group_get (ggi); - gg->gg_locks++; - } - - GBP_EPG_DBG ("add: %U", format_gbp_endpoint_group, gg); - - return (0); -} - -void -gbp_endpoint_group_unlock (index_t ggi) -{ - gbp_endpoint_group_t *gg; - - if (INDEX_INVALID == ggi) - return; - - gg = gbp_endpoint_group_get (ggi); - - gg->gg_locks--; - - if (0 == gg->gg_locks) - { - fib_protocol_t fproto; - - gg = pool_elt_at_index (gbp_endpoint_group_pool, ggi); - - gbp_itf_unlock (&gg->gg_uplink_itf); - - FOR_EACH_FIB_IP_PROTOCOL (fproto) - { - dpo_reset (&gg->gg_dpo[fproto]); - } - gbp_bridge_domain_unlock (gg->gg_gbd); - gbp_route_domain_unlock (gg->gg_rd); - - if (SCLASS_INVALID != gg->gg_sclass) - hash_unset (gbp_epg_sclass_db, gg->gg_sclass); - hash_unset (gbp_endpoint_group_db.gg_hash_sclass, gg->gg_sclass); - - pool_put (gbp_endpoint_group_pool, gg); - } -} - -int -gbp_endpoint_group_delete (sclass_t sclass) -{ - index_t ggi; - - ggi = gbp_endpoint_group_find (sclass); - - if (INDEX_INVALID != ggi) - { - GBP_EPG_DBG ("del: %U", format_gbp_endpoint_group, - gbp_endpoint_group_get (ggi)); - gbp_endpoint_group_unlock (ggi); - - return (0); - } - - return (VNET_API_ERROR_NO_SUCH_ENTRY); -} - -u32 -gbp_endpoint_group_get_bd_id (const gbp_endpoint_group_t * gg) -{ - const gbp_bridge_domain_t *gb; - - gb = gbp_bridge_domain_get (gg->gg_gbd); - - return (gb->gb_bd_id); -} - -index_t -gbp_endpoint_group_get_fib_index (const gbp_endpoint_group_t * gg, - fib_protocol_t fproto) -{ - const gbp_route_domain_t *grd; - - grd = gbp_route_domain_get (gg->gg_rd); - - return (grd->grd_fib_index[fproto]); -} - -void -gbp_endpoint_group_walk (gbp_endpoint_group_cb_t cb, void *ctx) -{ - gbp_endpoint_group_t *gbpe; - - /* *INDENT-OFF* */ - pool_foreach (gbpe, gbp_endpoint_group_pool) - { - if (!cb(gbpe, ctx)) - break; - } - /* *INDENT-ON* */ -} - -static clib_error_t * -gbp_endpoint_group_cli (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - gbp_endpoint_retention_t retention = { 0 }; - vnid_t vnid = VNID_INVALID, sclass; - vnet_main_t *vnm = vnet_get_main (); - u32 uplink_sw_if_index = ~0; - u32 bd_id = ~0; - u32 rd_id = ~0; - u8 add = 1; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "%U", unformat_vnet_sw_interface, - vnm, &uplink_sw_if_index)) - ; - else if (unformat (input, "add")) - add = 1; - else if (unformat (input, "del")) - add = 0; - else if (unformat (input, "epg %d", &vnid)) - ; - else if (unformat (input, "sclass %d", &sclass)) - ; - else if (unformat (input, "bd %d", &bd_id)) - ; - else if (unformat (input, "rd %d", &rd_id)) - ; - else - break; - } - - if (VNID_INVALID == vnid) - return clib_error_return (0, "EPG-ID must be specified"); - - if (add) - { - if (~0 == bd_id) - return clib_error_return (0, "Bridge-domain must be specified"); - if (~0 == rd_id) - return clib_error_return (0, "route-domain must be specified"); - - gbp_endpoint_group_add_and_lock (vnid, sclass, bd_id, rd_id, - uplink_sw_if_index, &retention); - } - else - gbp_endpoint_group_delete (vnid); - - return (NULL); -} - -/*? - * Configure a GBP Endpoint Group - * - * @cliexpar - * @cliexstart{gbp endpoint-group [del] epg <ID> bd <ID> rd <ID> [sclass <ID>] [<interface>]} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_endpoint_group_cli_node, static) = { - .path = "gbp endpoint-group", - .short_help = "gbp endpoint-group [del] epg <ID> bd <ID> rd <ID> [sclass <ID>] [<interface>]", - .function = gbp_endpoint_group_cli, -}; - -static u8 * -format_gbp_endpoint_retention (u8 * s, va_list * args) -{ - gbp_endpoint_retention_t *rt = va_arg (*args, gbp_endpoint_retention_t*); - - s = format (s, "[remote-EP-timeout:%d]", rt->remote_ep_timeout); - - return (s); -} - -u8 * -format_gbp_endpoint_group (u8 * s, va_list * args) -{ - gbp_endpoint_group_t *gg = va_arg (*args, gbp_endpoint_group_t*); - - if (NULL != gg) - s = format (s, "[%d] %d, sclass:%d bd:%d rd:%d uplink:%U retention:%U locks:%d", - gg - gbp_endpoint_group_pool, - gg->gg_vnid, - gg->gg_sclass, - gg->gg_gbd, - gg->gg_rd, - format_gbp_itf_hdl, gg->gg_uplink_itf, - format_gbp_endpoint_retention, &gg->gg_retention, - gg->gg_locks); - else - s = format (s, "NULL"); - - return (s); -} - -static int -gbp_endpoint_group_show_one (gbp_endpoint_group_t *gg, void *ctx) -{ - vlib_main_t *vm; - - vm = ctx; - vlib_cli_output (vm, " %U",format_gbp_endpoint_group, gg); - - return (1); -} - -static clib_error_t * -gbp_endpoint_group_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - vlib_cli_output (vm, "Endpoint-Groups:"); - gbp_endpoint_group_walk (gbp_endpoint_group_show_one, vm); - - return (NULL); -} - - -/*? - * Show Group Based Policy Endpoint_Groups and derived information - * - * @cliexpar - * @cliexstart{show gbp endpoint_group} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_endpoint_group_show_node, static) = { - .path = "show gbp endpoint-group", - .short_help = "show gbp endpoint-group\n", - .function = gbp_endpoint_group_show, -}; -/* *INDENT-ON* */ - -static clib_error_t * -gbp_endpoint_group_init (vlib_main_t * vm) -{ - gg_logger = vlib_log_register_class ("gbp", "epg"); - - return (NULL); -} - -VLIB_INIT_FUNCTION (gbp_endpoint_group_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_endpoint_group.h b/src/plugins/gbp/gbp_endpoint_group.h deleted file mode 100644 index c5fdff8463d..00000000000 --- a/src/plugins/gbp/gbp_endpoint_group.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_ENDPOINT_GROUP_H__ -#define __GBP_ENDPOINT_GROUP_H__ - -#include <plugins/gbp/gbp_types.h> -#include <plugins/gbp/gbp_itf.h> - -#include <vnet/fib/fib_types.h> - -/** - * Endpoint Retnetion Policy - */ -typedef struct gbp_endpoint_retention_t_ -{ - /** Aging timeout for remote endpoints */ - u32 remote_ep_timeout; -} gbp_endpoint_retention_t; - -/** - * An Endpoint Group representation - */ -typedef struct gpb_endpoint_group_t_ -{ - /** - * ID - */ - vnid_t gg_vnid; - - /** - * Sclass. Could be unset => ~0 - */ - u16 gg_sclass; - - /** - * Bridge-domain ID the EPG is in - */ - index_t gg_gbd; - - /** - * route-domain/IP-table ID the EPG is in - */ - index_t gg_rd; - - /** - * Is the EPG an external/NAT - */ - u8 gg_is_ext; - - /** - * the uplink interface dedicated to the EPG - */ - u32 gg_uplink_sw_if_index; - gbp_itf_hdl_t gg_uplink_itf; - - /** - * The DPO used in the L3 path for forwarding internal subnets - */ - dpo_id_t gg_dpo[FIB_PROTOCOL_IP_MAX]; - - /** - * Locks/references to this EPG - */ - u32 gg_locks; - - /** - * EP retention policy - */ - gbp_endpoint_retention_t gg_retention; -} gbp_endpoint_group_t; - -/** - * EPG DB, key'd on EGP-ID - */ -typedef struct gbp_endpoint_group_db_t_ -{ - uword *gg_hash_sclass; -} gbp_endpoint_group_db_t; - -extern int gbp_endpoint_group_add_and_lock (vnid_t vnid, - u16 sclass, - u32 bd_id, - u32 rd_id, - u32 uplink_sw_if_index, - const gbp_endpoint_retention_t * - retention); -extern index_t gbp_endpoint_group_find (sclass_t sclass); -extern int gbp_endpoint_group_delete (sclass_t sclass); -extern void gbp_endpoint_group_unlock (index_t index); -extern void gbp_endpoint_group_lock (index_t index); -extern u32 gbp_endpoint_group_get_bd_id (const gbp_endpoint_group_t *); - -extern gbp_endpoint_group_t *gbp_endpoint_group_get (index_t i); -extern index_t gbp_endpoint_group_get_fib_index (const gbp_endpoint_group_t * - gg, fib_protocol_t fproto); - -typedef int (*gbp_endpoint_group_cb_t) (gbp_endpoint_group_t * gbpe, - void *ctx); -extern void gbp_endpoint_group_walk (gbp_endpoint_group_cb_t bgpe, void *ctx); - - -extern u8 *format_gbp_endpoint_group (u8 * s, va_list * args); - -/** - * DP functions and databases - */ -extern gbp_endpoint_group_db_t gbp_endpoint_group_db; -extern gbp_endpoint_group_t *gbp_endpoint_group_pool; -extern uword *gbp_epg_sclass_db; - -always_inline u32 -gbp_epg_itf_lookup_sclass (sclass_t sclass) -{ - uword *p; - - p = hash_get (gbp_endpoint_group_db.gg_hash_sclass, sclass); - - if (NULL != p) - { - gbp_endpoint_group_t *gg; - - gg = pool_elt_at_index (gbp_endpoint_group_pool, p[0]); - return (gg->gg_uplink_sw_if_index); - } - return (~0); -} - -always_inline const dpo_id_t * -gbp_epg_dpo_lookup (sclass_t sclass, fib_protocol_t fproto) -{ - uword *p; - - p = hash_get (gbp_endpoint_group_db.gg_hash_sclass, sclass); - - if (NULL != p) - { - gbp_endpoint_group_t *gg; - - gg = pool_elt_at_index (gbp_endpoint_group_pool, p[0]); - return (&gg->gg_dpo[fproto]); - } - return (NULL); -} - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_ext_itf.c b/src/plugins/gbp/gbp_ext_itf.c deleted file mode 100644 index c5506661c2d..00000000000 --- a/src/plugins/gbp/gbp_ext_itf.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp_ext_itf.h> -#include <plugins/gbp/gbp_bridge_domain.h> -#include <plugins/gbp/gbp_route_domain.h> -#include <plugins/gbp/gbp_itf.h> - -/** - * Pool of GBP ext_itfs - */ -gbp_ext_itf_t *gbp_ext_itf_pool; - -/** - * external interface configs keyed by sw_if_index - */ -index_t *gbp_ext_itf_db; - -#define GBP_EXT_ITF_ID 0x00000080 - -/** - * logger - */ -vlib_log_class_t gx_logger; - -#define GBP_EXT_ITF_DBG(...) \ - vlib_log_debug (gx_logger, __VA_ARGS__); - -u8 * -format_gbp_ext_itf (u8 * s, va_list * args) -{ - gbp_ext_itf_t *gx = va_arg (*args, gbp_ext_itf_t *); - - return (format (s, "%U%s in %U", - format_gbp_itf_hdl, gx->gx_itf, - (gx->gx_flags & GBP_EXT_ITF_F_ANON) ? " [anon]" : "", - format_gbp_bridge_domain, gx->gx_bd)); -} - -int -gbp_ext_itf_add (u32 sw_if_index, u32 bd_id, u32 rd_id, u32 flags) -{ - gbp_ext_itf_t *gx; - index_t gxi; - - vec_validate_init_empty (gbp_ext_itf_db, sw_if_index, INDEX_INVALID); - - gxi = gbp_ext_itf_db[sw_if_index]; - - if (INDEX_INVALID == gxi) - { - gbp_route_domain_t *gr; - fib_protocol_t fproto; - index_t gbi, gri; - - gbi = gbp_bridge_domain_find_and_lock (bd_id); - - if (INDEX_INVALID == gbi) - return (VNET_API_ERROR_NO_SUCH_ENTRY); - - gri = gbp_route_domain_find_and_lock (rd_id); - - if (INDEX_INVALID == gri) - { - gbp_bridge_domain_unlock (gbi); - return (VNET_API_ERROR_NO_SUCH_ENTRY); - } - - pool_get_zero (gbp_ext_itf_pool, gx); - gxi = gx - gbp_ext_itf_pool; - - gr = gbp_route_domain_get (gri); - - gx->gx_bd = gbi; - gx->gx_rd = gri; - gbp_itf_hdl_reset (&gx->gx_itf); - - FOR_EACH_FIB_IP_PROTOCOL (fproto) - { - gx->gx_fib_index[fproto] = - gr->grd_fib_index[fib_proto_to_dpo (fproto)]; - } - - if (flags & GBP_EXT_ITF_F_ANON) - { - /* add interface to the BD */ - gx->gx_itf = gbp_itf_l2_add_and_lock (sw_if_index, gbi); - - /* setup GBP L2 features on this interface */ - gbp_itf_l2_set_input_feature (gx->gx_itf, - L2INPUT_FEAT_GBP_LPM_ANON_CLASSIFY | - L2INPUT_FEAT_LEARN); - gbp_itf_l2_set_output_feature (gx->gx_itf, - L2OUTPUT_FEAT_GBP_POLICY_LPM); - } - - gx->gx_flags = flags; - - gbp_ext_itf_db[sw_if_index] = gxi; - - GBP_EXT_ITF_DBG ("add: %U", format_gbp_ext_itf, gx); - - return (0); - } - - return (VNET_API_ERROR_ENTRY_ALREADY_EXISTS); -} - -int -gbp_ext_itf_delete (u32 sw_if_index) -{ - gbp_ext_itf_t *gx; - index_t gxi; - - if (vec_len (gbp_ext_itf_db) <= sw_if_index) - return (VNET_API_ERROR_INVALID_SW_IF_INDEX); - - gxi = gbp_ext_itf_db[sw_if_index]; - - if (INDEX_INVALID != gxi) - { - gx = pool_elt_at_index (gbp_ext_itf_pool, gxi); - - GBP_EXT_ITF_DBG ("del: %U", format_gbp_ext_itf, gx); - - gbp_itf_unlock (&gx->gx_itf); - gbp_route_domain_unlock (gx->gx_rd); - gbp_bridge_domain_unlock (gx->gx_bd); - - gbp_ext_itf_db[sw_if_index] = INDEX_INVALID; - pool_put (gbp_ext_itf_pool, gx); - - return (0); - } - return (VNET_API_ERROR_NO_SUCH_ENTRY); -} - -static clib_error_t * -gbp_ext_itf_add_del_cli (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u32 sw_if_index = ~0, bd_id = ~0, rd_id = ~0, flags = 0; - int add = 1; - int rv; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "del")) - add = 0; - else - if (unformat - (line_input, "%U", unformat_vnet_sw_interface, vnet_get_main (), - &sw_if_index)) - ; - else if (unformat (line_input, "bd %d", &bd_id)) - ; - else if (unformat (line_input, "rd %d", &rd_id)) - ; - else if (unformat (line_input, "anon-l3-out")) - flags |= GBP_EXT_ITF_F_ANON; - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, line_input); - } - unformat_free (line_input); - - if (~0 == sw_if_index) - return clib_error_return (0, "interface must be specified"); - - if (add) - { - if (~0 == bd_id) - return clib_error_return (0, "BD-ID must be specified"); - if (~0 == rd_id) - return clib_error_return (0, "RD-ID must be specified"); - rv = gbp_ext_itf_add (sw_if_index, bd_id, rd_id, flags); - } - else - rv = gbp_ext_itf_delete (sw_if_index); - - switch (rv) - { - case 0: - return 0; - case VNET_API_ERROR_ENTRY_ALREADY_EXISTS: - return clib_error_return (0, "interface already exists"); - case VNET_API_ERROR_NO_SUCH_ENTRY: /* fallthrough */ - case VNET_API_ERROR_INVALID_SW_IF_INDEX: - return clib_error_return (0, "unknown interface"); - default: - return clib_error_return (0, "error %d", rv); - } - - /* never reached */ - return 0; -} - -/*? - * Add Group Based Interface as anonymous L3out interface - * - * @cliexpar - * @cliexstart{gbp interface [del] anon-l3out <interface> bd <ID>} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_itf_anon_l3out_add_del_node, static) = { - .path = "gbp ext-itf", - .short_help = "gbp ext-itf [del] <interface> bd <ID> rd <ID> [anon-l3-out]\n", - .function = gbp_ext_itf_add_del_cli, -}; -/* *INDENT-ON* */ - -void -gbp_ext_itf_walk (gbp_ext_itf_cb_t cb, void *ctx) -{ - gbp_ext_itf_t *ge; - - /* *INDENT-OFF* */ - pool_foreach (ge, gbp_ext_itf_pool) - { - if (!cb(ge, ctx)) - break; - } - /* *INDENT-ON* */ -} - -static walk_rc_t -gbp_ext_itf_show_one (gbp_ext_itf_t * gx, void *ctx) -{ - vlib_cli_output (ctx, " %U", format_gbp_ext_itf, gx); - - return (WALK_CONTINUE); -} - -static clib_error_t * -gbp_ext_itf_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - vlib_cli_output (vm, "External-Interfaces:"); - gbp_ext_itf_walk (gbp_ext_itf_show_one, vm); - - return (NULL); -} - -/*? - * Show Group Based Policy external interface and derived information - * - * @cliexpar - * @cliexstart{show gbp ext-itf} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_ext_itf_show_node, static) = { - .path = "show gbp ext-itf", - .short_help = "show gbp ext-itf\n", - .function = gbp_ext_itf_show, -}; -/* *INDENT-ON* */ - -static clib_error_t * -gbp_ext_itf_init (vlib_main_t * vm) -{ - gx_logger = vlib_log_register_class ("gbp", "ext-itf"); - - return (NULL); -} - -VLIB_INIT_FUNCTION (gbp_ext_itf_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_ext_itf.h b/src/plugins/gbp/gbp_ext_itf.h deleted file mode 100644 index 03b1992ca45..00000000000 --- a/src/plugins/gbp/gbp_ext_itf.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_EXT_ITF_H__ -#define __GBP_EXT_ITF_H__ - -#include <gbp/gbp.h> - -enum -{ - GBP_EXT_ITF_F_NONE = 0, - GBP_EXT_ITF_F_ANON = 1 << 0, -}; - -/** - * An external interface maps directly to an oflex L3ExternalInterface. - * The special characteristics of an external interface is the way the source - * EPG is determined for input packets which, like a recirc interface, is via - * a LPM. - */ -typedef struct gpb_ext_itf_t_ -{ - /** - * The interface - */ - gbp_itf_hdl_t gx_itf; - - /** - * The BD this external interface is a member of - */ - index_t gx_bd; - - /** - * The RD this external interface is a member of - */ - index_t gx_rd; - - /** - * cached FIB indices from the RD - */ - u32 gx_fib_index[DPO_PROTO_NUM]; - - /** - * The associated flags - */ - u32 gx_flags; - -} gbp_ext_itf_t; - - -extern int gbp_ext_itf_add (u32 sw_if_index, u32 bd_id, u32 rd_id, u32 flags); -extern int gbp_ext_itf_delete (u32 sw_if_index); - -extern u8 *format_gbp_ext_itf (u8 * s, va_list * args); - -typedef walk_rc_t (*gbp_ext_itf_cb_t) (gbp_ext_itf_t * gbpe, void *ctx); -extern void gbp_ext_itf_walk (gbp_ext_itf_cb_t bgpe, void *ctx); - - -/** - * Exposed types for the data-plane - */ -extern gbp_ext_itf_t *gbp_ext_itf_pool; -extern index_t *gbp_ext_itf_db; - -always_inline gbp_ext_itf_t * -gbp_ext_itf_get (u32 sw_if_index) -{ - return (pool_elt_at_index (gbp_ext_itf_pool, gbp_ext_itf_db[sw_if_index])); -} - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_fwd.c b/src/plugins/gbp/gbp_fwd.c deleted file mode 100644 index 4ecc4779b92..00000000000 --- a/src/plugins/gbp/gbp_fwd.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019 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. - */ -#include <plugins/gbp/gbp.h> -#include <vnet/l2/l2_input.h> -#include <plugins/gbp/gbp_learn.h> - -/** - * Grouping of global data for the GBP source EPG classification feature - */ -typedef struct gbp_fwd_main_t_ -{ - /** - * Next nodes for L2 output features - */ - u32 l2_input_feat_next[32]; -} gbp_fwd_main_t; - -gbp_fwd_main_t gbp_fwd_main; - -static clib_error_t * -gbp_fwd_init (vlib_main_t * vm) -{ - gbp_fwd_main_t *gpm = &gbp_fwd_main; - vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "gbp-fwd"); - - /* Initialize the feature next-node indices */ - feat_bitmap_init_next_nodes (vm, - node->index, - L2INPUT_N_FEAT, - l2input_get_feat_names (), - gpm->l2_input_feat_next); - - return 0; -} - -VLIB_INIT_FUNCTION (gbp_fwd_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_fwd_dpo.c b/src/plugins/gbp/gbp_fwd_dpo.c deleted file mode 100644 index b1023f5e78f..00000000000 --- a/src/plugins/gbp/gbp_fwd_dpo.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp.h> -#include <plugins/gbp/gbp_fwd_dpo.h> - -#include <vnet/ethernet/ethernet.h> - - -#ifndef CLIB_MARCH_VARIANT -/** - * The 'DB' of GBP FWD DPOs. - * There is one per-proto - */ -static index_t gbp_fwd_dpo_db[DPO_PROTO_NUM] = { INDEX_INVALID }; - -/** - * DPO type registered for these GBP FWD - */ -static dpo_type_t gbp_fwd_dpo_type; - -/** - * @brief pool of all interface DPOs - */ -gbp_fwd_dpo_t *gbp_fwd_dpo_pool; - -static gbp_fwd_dpo_t * -gbp_fwd_dpo_alloc (void) -{ - gbp_fwd_dpo_t *gfd; - - pool_get (gbp_fwd_dpo_pool, gfd); - - return (gfd); -} - -static inline gbp_fwd_dpo_t * -gbp_fwd_dpo_get_from_dpo (const dpo_id_t * dpo) -{ - ASSERT (gbp_fwd_dpo_type == dpo->dpoi_type); - - return (gbp_fwd_dpo_get (dpo->dpoi_index)); -} - -static inline index_t -gbp_fwd_dpo_get_index (gbp_fwd_dpo_t * gfd) -{ - return (gfd - gbp_fwd_dpo_pool); -} - -static void -gbp_fwd_dpo_lock (dpo_id_t * dpo) -{ - gbp_fwd_dpo_t *gfd; - - gfd = gbp_fwd_dpo_get_from_dpo (dpo); - gfd->gfd_locks++; -} - -static void -gbp_fwd_dpo_unlock (dpo_id_t * dpo) -{ - gbp_fwd_dpo_t *gfd; - - gfd = gbp_fwd_dpo_get_from_dpo (dpo); - gfd->gfd_locks--; - - if (0 == gfd->gfd_locks) - { - gbp_fwd_dpo_db[gfd->gfd_proto] = INDEX_INVALID; - pool_put (gbp_fwd_dpo_pool, gfd); - } -} - -void -gbp_fwd_dpo_add_or_lock (dpo_proto_t dproto, dpo_id_t * dpo) -{ - gbp_fwd_dpo_t *gfd; - - if (INDEX_INVALID == gbp_fwd_dpo_db[dproto]) - { - gfd = gbp_fwd_dpo_alloc (); - - gfd->gfd_proto = dproto; - - gbp_fwd_dpo_db[dproto] = gbp_fwd_dpo_get_index (gfd); - } - else - { - gfd = gbp_fwd_dpo_get (gbp_fwd_dpo_db[dproto]); - } - - dpo_set (dpo, gbp_fwd_dpo_type, dproto, gbp_fwd_dpo_get_index (gfd)); -} - -u8 * -format_gbp_fwd_dpo (u8 * s, va_list * ap) -{ - index_t index = va_arg (*ap, index_t); - CLIB_UNUSED (u32 indent) = va_arg (*ap, u32); - gbp_fwd_dpo_t *gfd = gbp_fwd_dpo_get (index); - - return (format (s, "gbp-fwd-dpo: %U", format_dpo_proto, gfd->gfd_proto)); -} - -const static dpo_vft_t gbp_fwd_dpo_vft = { - .dv_lock = gbp_fwd_dpo_lock, - .dv_unlock = gbp_fwd_dpo_unlock, - .dv_format = format_gbp_fwd_dpo, -}; - -/** - * @brief The per-protocol VLIB graph nodes that are assigned to a glean - * object. - * - * this means that these graph nodes are ones from which a glean is the - * parent object in the DPO-graph. - */ -const static char *const gbp_fwd_dpo_ip4_nodes[] = { - "ip4-gbp-fwd-dpo", - NULL, -}; - -const static char *const gbp_fwd_dpo_ip6_nodes[] = { - "ip6-gbp-fwd-dpo", - NULL, -}; - -const static char *const *const gbp_fwd_dpo_nodes[DPO_PROTO_NUM] = { - [DPO_PROTO_IP4] = gbp_fwd_dpo_ip4_nodes, - [DPO_PROTO_IP6] = gbp_fwd_dpo_ip6_nodes, -}; - -dpo_type_t -gbp_fwd_dpo_get_type (void) -{ - return (gbp_fwd_dpo_type); -} - -static clib_error_t * -gbp_fwd_dpo_module_init (vlib_main_t * vm) -{ - dpo_proto_t dproto; - - FOR_EACH_DPO_PROTO (dproto) - { - gbp_fwd_dpo_db[dproto] = INDEX_INVALID; - } - - gbp_fwd_dpo_type = dpo_register_new_type (&gbp_fwd_dpo_vft, - gbp_fwd_dpo_nodes); - - return (NULL); -} - -VLIB_INIT_FUNCTION (gbp_fwd_dpo_module_init); -#endif /* CLIB_MARCH_VARIANT */ - -typedef struct gbp_fwd_dpo_trace_t_ -{ - u32 sclass; - u32 dpo_index; -} gbp_fwd_dpo_trace_t; - -typedef enum -{ - GBP_FWD_DROP, - GBP_FWD_FWD, - GBP_FWD_N_NEXT, -} gbp_fwd_next_t; - -always_inline uword -gbp_fwd_dpo_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame, fib_protocol_t fproto) -{ - u32 n_left_from, next_index, *from, *to_next; - - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - const dpo_id_t *next_dpo0; - vlib_buffer_t *b0; - sclass_t sclass0; - u32 bi0, next0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - sclass0 = vnet_buffer2 (b0)->gbp.sclass; - next_dpo0 = gbp_epg_dpo_lookup (sclass0, fproto); - - if (PREDICT_TRUE (NULL != next_dpo0)) - { - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = next_dpo0->dpoi_index; - next0 = GBP_FWD_FWD; - } - else - { - next0 = GBP_FWD_DROP; - } - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - gbp_fwd_dpo_trace_t *tr; - - tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); - tr->sclass = sclass0; - tr->dpo_index = (NULL != next_dpo0 ? - next_dpo0->dpoi_index : ~0); - } - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, next0); - } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - return from_frame->n_vectors; -} - -static u8 * -format_gbp_fwd_dpo_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - gbp_fwd_dpo_trace_t *t = va_arg (*args, gbp_fwd_dpo_trace_t *); - - s = format (s, " sclass:%d dpo:%d", t->sclass, t->dpo_index); - - return s; -} - -VLIB_NODE_FN (ip4_gbp_fwd_dpo_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - return (gbp_fwd_dpo_inline (vm, node, from_frame, FIB_PROTOCOL_IP4)); -} - -VLIB_NODE_FN (ip6_gbp_fwd_dpo_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - return (gbp_fwd_dpo_inline (vm, node, from_frame, FIB_PROTOCOL_IP6)); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (ip4_gbp_fwd_dpo_node) = { - .name = "ip4-gbp-fwd-dpo", - .vector_size = sizeof (u32), - .format_trace = format_gbp_fwd_dpo_trace, - .n_next_nodes = GBP_FWD_N_NEXT, - .next_nodes = - { - [GBP_FWD_DROP] = "ip4-drop", - [GBP_FWD_FWD] = "ip4-dvr-dpo", - } -}; -VLIB_REGISTER_NODE (ip6_gbp_fwd_dpo_node) = { - .name = "ip6-gbp-fwd-dpo", - .vector_size = sizeof (u32), - .format_trace = format_gbp_fwd_dpo_trace, - .n_next_nodes = GBP_FWD_N_NEXT, - .next_nodes = - { - [GBP_FWD_DROP] = "ip6-drop", - [GBP_FWD_FWD] = "ip6-dvr-dpo", - } -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_fwd_dpo.h b/src/plugins/gbp/gbp_fwd_dpo.h deleted file mode 100644 index 6092d6241b5..00000000000 --- a/src/plugins/gbp/gbp_fwd_dpo.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_FWD_DPO_H__ -#define __GBP_FWD_DPO_H__ - -#include <vnet/dpo/dpo.h> - -/** - * @brief - * The GBP FWD DPO. Used in the L3 path to select the correct EPG uplink - * based on the source EPG. - */ -typedef struct gbp_fwd_dpo_t_ -{ - /** - * The protocol of packets using this DPO - */ - dpo_proto_t gfd_proto; - - /** - * number of locks. - */ - u16 gfd_locks; -} gbp_fwd_dpo_t; - -extern void gbp_fwd_dpo_add_or_lock (dpo_proto_t dproto, dpo_id_t * dpo); - -extern dpo_type_t gbp_fwd_dpo_get_type (void); - -/** - * @brief pool of all interface DPOs - */ -extern gbp_fwd_dpo_t *gbp_fwd_dpo_pool; - -static inline gbp_fwd_dpo_t * -gbp_fwd_dpo_get (index_t index) -{ - return (pool_elt_at_index (gbp_fwd_dpo_pool, index)); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ - -#endif diff --git a/src/plugins/gbp/gbp_fwd_node.c b/src/plugins/gbp/gbp_fwd_node.c deleted file mode 100644 index 6ea56fd8074..00000000000 --- a/src/plugins/gbp/gbp_fwd_node.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp.h> -#include <vnet/l2/l2_input.h> - -#define foreach_gbp_fwd \ - _(DROP, "drop") \ - _(OUTPUT, "output") - -typedef enum -{ -#define _(sym,str) GBP_FWD_ERROR_##sym, - foreach_gbp_fwd -#undef _ - GBP_FWD_N_ERROR, -} gbp_fwd_error_t; - -static char *gbp_fwd_error_strings[] = { -#define _(sym,string) string, - foreach_gbp_fwd -#undef _ -}; - -typedef enum -{ -#define _(sym,str) GBP_FWD_NEXT_##sym, - foreach_gbp_fwd -#undef _ - GBP_FWD_N_NEXT, -} gbp_fwd_next_t; - -/** - * per-packet trace data - */ -typedef struct gbp_fwd_trace_t_ -{ - /* per-pkt trace data */ - sclass_t sclass; - u32 sw_if_index; -} gbp_fwd_trace_t; - -VLIB_NODE_FN (gbp_fwd_node) (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next; - u32 next_index; - - next_index = 0; - n_left_from = frame->n_vectors; - from = vlib_frame_vector_args (frame); - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0, sw_if_index0; - gbp_fwd_next_t next0; - vlib_buffer_t *b0; - sclass_t sclass0; - - next0 = GBP_FWD_NEXT_DROP; - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - /* - * lookup the uplink based on src EPG - */ - sclass0 = vnet_buffer2 (b0)->gbp.sclass; - - sw_if_index0 = gbp_epg_itf_lookup_sclass (sclass0); - - if (~0 != sw_if_index0) - { - vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0; - - next0 = GBP_FWD_NEXT_OUTPUT; - } - /* - * else - * don't know the uplink interface for this EPG => drop - */ - - if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_IS_TRACED))) - { - gbp_fwd_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); - t->sclass = sclass0; - t->sw_if_index = sw_if_index0; - } - - /* verify speculative enqueue, maybe switch current next frame */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - -/* packet trace format function */ -static u8 * -format_gbp_fwd_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - gbp_fwd_trace_t *t = va_arg (*args, gbp_fwd_trace_t *); - - s = format (s, "sclass:%d", t->sclass); - - return s; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (gbp_fwd_node) = { - .name = "gbp-fwd", - .vector_size = sizeof (u32), - .format_trace = format_gbp_fwd_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(gbp_fwd_error_strings), - .error_strings = gbp_fwd_error_strings, - - .n_next_nodes = GBP_FWD_N_NEXT, - - .next_nodes = { - [GBP_FWD_NEXT_DROP] = "error-drop", - [GBP_FWD_NEXT_OUTPUT] = "l2-output", - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_itf.c b/src/plugins/gbp/gbp_itf.c deleted file mode 100644 index 738a7ac2e39..00000000000 --- a/src/plugins/gbp/gbp_itf.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp_itf.h> -#include <plugins/gbp/gbp_bridge_domain.h> -#include <plugins/gbp/gbp_route_domain.h> - -#include <vnet/ip/ip.h> - -#define foreach_gbp_itf_mode \ - _(L2, "l2") \ - _(L3, "L3") - -typedef enum gbp_ift_mode_t_ -{ -#define _(s,v) GBP_ITF_MODE_##s, - foreach_gbp_itf_mode -#undef _ -} gbp_itf_mode_t; - -/** - * Attributes and configurations attached to interfaces by GBP - */ -typedef struct gbp_itf_t_ -{ - /** - * Number of references to this interface - */ - u32 gi_locks; - - /** - * The interface this wrapper is managing - */ - u32 gi_sw_if_index; - - /** - * The mode of the interface - */ - gbp_itf_mode_t gi_mode; - - /** - * Users of this interface - this is encoded in the user's handle - */ - u32 *gi_users; - - /** - * L2/L3 Features configured by each user - */ - u32 *gi_input_fbs; - u32 gi_input_fb; - u32 *gi_output_fbs; - u32 gi_output_fb; - - /** - * function to call when the interface is deleted. - */ - gbp_itf_free_fn_t gi_free_fn; - - union - { - /** - * GBP BD or RD index - */ - u32 gi_gbi; - index_t gi_gri; - }; -} gbp_itf_t; - -static gbp_itf_t *gbp_itf_pool; -static uword *gbp_itf_db; - -static const char *gbp_itf_feat_bit_pos_to_arc[] = { -#define _(s,v,a) [GBP_ITF_L3_FEAT_POS_##s] = a, - foreach_gdb_l3_feature -#undef _ -}; - -static const char *gbp_itf_feat_bit_pos_to_feat[] = { -#define _(s,v,a) [GBP_ITF_L3_FEAT_POS_##s] = v, - foreach_gdb_l3_feature -#undef _ -}; - -u8 * -format_gbp_itf_l3_feat (u8 * s, va_list * args) -{ - gbp_itf_l3_feat_t flags = va_arg (*args, gbp_itf_l3_feat_t); - -#define _(a, b, c) \ - if (flags & GBP_ITF_L3_FEAT_##a) \ - s = format (s, "%s ", b); - foreach_gdb_l3_feature -#undef _ - return (s); -} - -void -gbp_itf_hdl_reset (gbp_itf_hdl_t * gh) -{ - *gh = GBP_ITF_HDL_INVALID; -} - -bool -gbp_itf_hdl_is_valid (gbp_itf_hdl_t gh) -{ - return (gh.gh_which != GBP_ITF_HDL_INVALID.gh_which); -} - -static gbp_itf_t * -gbp_itf_get (index_t gii) -{ - if (pool_is_free_index (gbp_itf_pool, gii)) - return (NULL); - - return (pool_elt_at_index (gbp_itf_pool, gii)); -} - -static gbp_itf_t * -gbp_itf_find (u32 sw_if_index) -{ - uword *p; - - p = hash_get (gbp_itf_db, sw_if_index); - - if (NULL != p) - return (gbp_itf_get (p[0])); - - return (NULL); -} - -static gbp_itf_t * -gbp_itf_find_hdl (gbp_itf_hdl_t gh) -{ - return (gbp_itf_find (gh.gh_which)); -} - -u32 -gbp_itf_get_sw_if_index (gbp_itf_hdl_t hdl) -{ - return (hdl.gh_which); -} - -static gbp_itf_hdl_t -gbp_itf_mk_hdl (gbp_itf_t * gi) -{ - gbp_itf_hdl_t gh; - u32 *useri; - - pool_get (gi->gi_users, useri); - *useri = 0; - - gh.gh_who = useri - gi->gi_users; - gh.gh_which = gi->gi_sw_if_index; - - return (gh); -} - -static gbp_itf_hdl_t -gbp_itf_l2_add_and_lock_i (u32 sw_if_index, index_t gbi, gbp_itf_free_fn_t ff) -{ - gbp_itf_t *gi; - - gi = gbp_itf_find (sw_if_index); - - if (NULL == gi) - { - pool_get_zero (gbp_itf_pool, gi); - - gi->gi_sw_if_index = sw_if_index; - gi->gi_gbi = gbi; - gi->gi_mode = GBP_ITF_MODE_L2; - gi->gi_free_fn = ff; - - gbp_bridge_domain_itf_add (gi->gi_gbi, gi->gi_sw_if_index, - L2_BD_PORT_TYPE_NORMAL); - - hash_set (gbp_itf_db, gi->gi_sw_if_index, gi - gbp_itf_pool); - } - - gi->gi_locks++; - - return (gbp_itf_mk_hdl (gi)); -} - -gbp_itf_hdl_t -gbp_itf_l2_add_and_lock (u32 sw_if_index, index_t gbi) -{ - return (gbp_itf_l2_add_and_lock_i (sw_if_index, gbi, NULL)); -} - -gbp_itf_hdl_t -gbp_itf_l2_add_and_lock_w_free (u32 sw_if_index, - index_t gbi, gbp_itf_free_fn_t ff) -{ - return (gbp_itf_l2_add_and_lock_i (sw_if_index, gbi, ff)); -} - -gbp_itf_hdl_t -gbp_itf_l3_add_and_lock_i (u32 sw_if_index, index_t gri, gbp_itf_free_fn_t ff) -{ - gbp_itf_t *gi; - - gi = gbp_itf_find (sw_if_index); - - if (NULL == gi) - { - const gbp_route_domain_t *grd; - fib_protocol_t fproto; - - pool_get_zero (gbp_itf_pool, gi); - - gi->gi_sw_if_index = sw_if_index; - gi->gi_mode = GBP_ITF_MODE_L3; - gi->gi_gri = gri; - gi->gi_free_fn = ff; - - grd = gbp_route_domain_get (gi->gi_gri); - - ip4_sw_interface_enable_disable (gi->gi_sw_if_index, 1); - ip6_sw_interface_enable_disable (gi->gi_sw_if_index, 1); - - FOR_EACH_FIB_IP_PROTOCOL (fproto) - ip_table_bind (fproto, gi->gi_sw_if_index, grd->grd_table_id[fproto]); - - hash_set (gbp_itf_db, gi->gi_sw_if_index, gi - gbp_itf_pool); - } - - gi->gi_locks++; - - return (gbp_itf_mk_hdl (gi)); -} - -gbp_itf_hdl_t -gbp_itf_l3_add_and_lock (u32 sw_if_index, index_t gri) -{ - return (gbp_itf_l3_add_and_lock_i (sw_if_index, gri, NULL)); -} - -gbp_itf_hdl_t -gbp_itf_l3_add_and_lock_w_free (u32 sw_if_index, - index_t gri, gbp_itf_free_fn_t ff) -{ - return (gbp_itf_l3_add_and_lock_i (sw_if_index, gri, ff)); -} - -void -gbp_itf_lock (gbp_itf_hdl_t gh) -{ - gbp_itf_t *gi; - - if (!gbp_itf_hdl_is_valid (gh)) - return; - - gi = gbp_itf_find_hdl (gh); - - gi->gi_locks++; -} - -gbp_itf_hdl_t -gbp_itf_clone_and_lock (gbp_itf_hdl_t gh) -{ - gbp_itf_t *gi; - - if (!gbp_itf_hdl_is_valid (gh)) - return (GBP_ITF_HDL_INVALID); - - gi = gbp_itf_find_hdl (gh); - - gi->gi_locks++; - - return (gbp_itf_mk_hdl (gi)); -} - -void -gbp_itf_unlock (gbp_itf_hdl_t * gh) -{ - gbp_itf_t *gi; - - if (!gbp_itf_hdl_is_valid (*gh)) - return; - - gi = gbp_itf_find_hdl (*gh); - ASSERT (gi->gi_locks > 0); - gi->gi_locks--; - - if (0 == gi->gi_locks) - { - if (GBP_ITF_MODE_L2 == gi->gi_mode) - { - gbp_itf_l2_set_input_feature (*gh, L2INPUT_FEAT_NONE); - gbp_itf_l2_set_output_feature (*gh, L2OUTPUT_FEAT_NONE); - gbp_bridge_domain_itf_del (gi->gi_gbi, - gi->gi_sw_if_index, - L2_BD_PORT_TYPE_NORMAL); - } - else - { - fib_protocol_t fproto; - - gbp_itf_l3_set_input_feature (*gh, GBP_ITF_L3_FEAT_NONE); - FOR_EACH_FIB_IP_PROTOCOL (fproto) - ip_table_bind (fproto, gi->gi_sw_if_index, 0); - - ip4_sw_interface_enable_disable (gi->gi_sw_if_index, 0); - ip6_sw_interface_enable_disable (gi->gi_sw_if_index, 0); - } - - hash_unset (gbp_itf_db, gi->gi_sw_if_index); - - if (gi->gi_free_fn) - gi->gi_free_fn (gi->gi_sw_if_index); - - pool_free (gi->gi_users); - vec_free (gi->gi_input_fbs); - vec_free (gi->gi_output_fbs); - - memset (gi, 0, sizeof (*gi)); - } - - gbp_itf_hdl_reset (gh); -} - -void -gbp_itf_l3_set_input_feature (gbp_itf_hdl_t gh, gbp_itf_l3_feat_t feats) -{ - u32 diff_fb, new_fb, *fb, feat; - gbp_itf_t *gi; - - gi = gbp_itf_find_hdl (gh); - - if (NULL == gi || GBP_ITF_MODE_L3 != gi->gi_mode) - return; - - vec_validate (gi->gi_input_fbs, gh.gh_who); - gi->gi_input_fbs[gh.gh_who] = feats; - - new_fb = 0; - vec_foreach (fb, gi->gi_input_fbs) - { - new_fb |= *fb; - } - - /* add new features */ - diff_fb = (gi->gi_input_fb ^ new_fb) & new_fb; - - /* *INDENT-OFF* */ - foreach_set_bit (feat, diff_fb, - ({ - vnet_feature_enable_disable (gbp_itf_feat_bit_pos_to_arc[feat], - gbp_itf_feat_bit_pos_to_feat[feat], - gi->gi_sw_if_index, 1, 0, 0); - })); - /* *INDENT-ON* */ - - /* remove unneeded features */ - diff_fb = (gi->gi_input_fb ^ new_fb) & gi->gi_input_fb; - - /* *INDENT-OFF* */ - foreach_set_bit (feat, diff_fb, - ({ - vnet_feature_enable_disable (gbp_itf_feat_bit_pos_to_arc[feat], - gbp_itf_feat_bit_pos_to_feat[feat], - gi->gi_sw_if_index, 0, 0, 0); - })); - /* *INDENT-ON* */ - - gi->gi_input_fb = new_fb; -} - -void -gbp_itf_l2_set_input_feature (gbp_itf_hdl_t gh, l2input_feat_masks_t feats) -{ - u32 diff_fb, new_fb, *fb, feat; - gbp_itf_t *gi; - - gi = gbp_itf_find_hdl (gh); - - if (NULL == gi || GBP_ITF_MODE_L2 != gi->gi_mode) - { - ASSERT (0); - return; - } - - vec_validate (gi->gi_input_fbs, gh.gh_who); - gi->gi_input_fbs[gh.gh_who] = feats; - - new_fb = 0; - vec_foreach (fb, gi->gi_input_fbs) - { - new_fb |= *fb; - } - - /* add new features */ - diff_fb = (gi->gi_input_fb ^ new_fb) & new_fb; - - /* *INDENT-OFF* */ - foreach_set_bit (feat, diff_fb, - ({ - l2input_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 1); - })); - /* *INDENT-ON* */ - - /* remove unneeded features */ - diff_fb = (gi->gi_input_fb ^ new_fb) & gi->gi_input_fb; - - /* *INDENT-OFF* */ - foreach_set_bit (feat, diff_fb, - ({ - l2input_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 0); - })); - /* *INDENT-ON* */ - - gi->gi_input_fb = new_fb; -} - -void -gbp_itf_l2_set_output_feature (gbp_itf_hdl_t gh, l2output_feat_masks_t feats) -{ - u32 diff_fb, new_fb, *fb, feat; - gbp_itf_t *gi; - - gi = gbp_itf_find_hdl (gh); - - if (NULL == gi || GBP_ITF_MODE_L2 != gi->gi_mode) - { - ASSERT (0); - return; - } - - vec_validate (gi->gi_output_fbs, gh.gh_who); - gi->gi_output_fbs[gh.gh_who] = feats; - - new_fb = 0; - vec_foreach (fb, gi->gi_output_fbs) - { - new_fb |= *fb; - } - - /* add new features */ - diff_fb = (gi->gi_output_fb ^ new_fb) & new_fb; - - /* *INDENT-OFF* */ - foreach_set_bit (feat, diff_fb, - ({ - l2output_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 1); - })); - /* *INDENT-ON* */ - - /* remove unneeded features */ - diff_fb = (gi->gi_output_fb ^ new_fb) & gi->gi_output_fb; - - /* *INDENT-OFF* */ - foreach_set_bit (feat, diff_fb, - ({ - l2output_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 0); - })); - /* *INDENT-ON* */ - - gi->gi_output_fb = new_fb; -} - -static u8 * -format_gbp_itf_mode (u8 * s, va_list * args) -{ - gbp_itf_mode_t mode = va_arg (*args, gbp_itf_mode_t); - - switch (mode) - { -#define _(a,v) \ - case GBP_ITF_MODE_##a: \ - return format(s, "%s", v); - foreach_gbp_itf_mode -#undef _ - } - return (s); -} - -static u8 * -format_gbp_itf (u8 * s, va_list * args) -{ - index_t gii = va_arg (*args, index_t); - gbp_itf_t *gi; - - if (INDEX_INVALID == gii) - return (format (s, "unset")); - - gi = gbp_itf_get (gii); - - s = format (s, "%U locks:%d mode:%U ", - format_vnet_sw_if_index_name, vnet_get_main (), - gi->gi_sw_if_index, gi->gi_locks, - format_gbp_itf_mode, gi->gi_mode); - - if (GBP_ITF_MODE_L2 == gi->gi_mode) - s = format (s, "gbp-bd:%d input-feats:[%U] output-feats:[%U]", - gi->gi_gbi, - format_l2_input_features, gi->gi_input_fb, 0, - format_l2_output_features, gi->gi_output_fb, 0); - else - s = format (s, "gbp-rd:%d input-feats:[%U] output-feats:[%U]", - gi->gi_gbi, - format_gbp_itf_l3_feat, gi->gi_input_fb, - format_gbp_itf_l3_feat, gi->gi_output_fb); - - return (s); -} - -u8 * -format_gbp_itf_hdl (u8 * s, va_list * args) -{ - gbp_itf_hdl_t gh = va_arg (*args, gbp_itf_hdl_t); - gbp_itf_t *gi; - - gi = gbp_itf_find_hdl (gh); - - if (NULL == gi) - return format (s, "INVALID"); - - return (format (s, "%U", format_gbp_itf, gi - gbp_itf_pool)); -} - -static clib_error_t * -gbp_itf_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - u32 gii; - - vlib_cli_output (vm, "Interfaces:"); - - /* *INDENT-OFF* */ - pool_foreach_index (gii, gbp_itf_pool) - { - vlib_cli_output (vm, " [%d] %U", gii, format_gbp_itf, gii); - } - /* *INDENT-ON* */ - - return (NULL); -} - -/*? - * Show Group Based Interfaces - * - * @cliexpar - * @cliexstart{show gbp contract} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_contract_show_node, static) = { - .path = "show gbp interface", - .short_help = "show gbp interface\n", - .function = gbp_itf_show, -}; -/* *INDENT-ON* */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_itf.h b/src/plugins/gbp/gbp_itf.h deleted file mode 100644 index 23a09b2a9ff..00000000000 --- a/src/plugins/gbp/gbp_itf.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_INTERFACE_H__ -#define __GBP_INTERFACE_H__ - -#include <vnet/l2/l2_input.h> -#include <vnet/l2/l2_output.h> -#include <vnet/dpo/dpo.h> - - -#define foreach_gdb_l3_feature \ - _(LEARN_IP4, "gbp-learn-ip4", "ip4-unicast") \ - _(LEARN_IP6, "gbp-learn-ip6", "ip6-unicast") - -typedef enum gbp_itf_l3_feat_pos_t_ -{ -#define _(s,v,a) GBP_ITF_L3_FEAT_POS_##s, - foreach_gdb_l3_feature -#undef _ -} gbp_itf_l3_feat_pos_t; - -typedef enum gbp_itf_l3_feat_t_ -{ - GBP_ITF_L3_FEAT_NONE, -#define _(s,v,a) GBP_ITF_L3_FEAT_##s = (1 << GBP_ITF_L3_FEAT_POS_##s), - foreach_gdb_l3_feature -#undef _ -} gbp_itf_l3_feat_t; - -#define GBP_ITF_L3_FEAT_LEARN (GBP_ITF_L3_FEAT_LEARN_IP4|GBP_ITF_L3_FEAT_LEARN_IP6) - -typedef struct gbp_itf_hdl_t_ -{ - union - { - struct - { - u32 gh_who; - u32 gh_which; - }; - }; -} gbp_itf_hdl_t; - -#define GBP_ITF_HDL_INIT {.gh_which = ~0} -const static gbp_itf_hdl_t GBP_ITF_HDL_INVALID = GBP_ITF_HDL_INIT; - -extern void gbp_itf_hdl_reset (gbp_itf_hdl_t * gh); -extern bool gbp_itf_hdl_is_valid (gbp_itf_hdl_t gh); - -typedef void (*gbp_itf_free_fn_t) (u32 sw_if_index); - -extern gbp_itf_hdl_t gbp_itf_l2_add_and_lock (u32 sw_if_index, u32 bd_index); -extern gbp_itf_hdl_t gbp_itf_l3_add_and_lock (u32 sw_if_index, index_t gri); -extern gbp_itf_hdl_t gbp_itf_l2_add_and_lock_w_free (u32 sw_if_index, - u32 bd_index, - gbp_itf_free_fn_t ff); -extern gbp_itf_hdl_t gbp_itf_l3_add_and_lock_w_free (u32 sw_if_index, - index_t gri, - gbp_itf_free_fn_t ff); - -extern void gbp_itf_unlock (gbp_itf_hdl_t * hdl); -extern void gbp_itf_lock (gbp_itf_hdl_t hdl); -extern gbp_itf_hdl_t gbp_itf_clone_and_lock (gbp_itf_hdl_t hdl); -extern u32 gbp_itf_get_sw_if_index (gbp_itf_hdl_t hdl); - -extern void gbp_itf_l2_set_input_feature (gbp_itf_hdl_t hdl, - l2input_feat_masks_t feats); -extern void gbp_itf_l2_set_output_feature (gbp_itf_hdl_t hdl, - l2output_feat_masks_t feats); - -extern void gbp_itf_l3_set_input_feature (gbp_itf_hdl_t hdl, - gbp_itf_l3_feat_t feats); - -extern u8 *format_gbp_itf_hdl (u8 * s, va_list * args); - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_learn.c b/src/plugins/gbp/gbp_learn.c deleted file mode 100644 index af3a6fb52ac..00000000000 --- a/src/plugins/gbp/gbp_learn.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp.h> -#include <plugins/gbp/gbp_learn.h> -#include <plugins/gbp/gbp_bridge_domain.h> - -#include <vnet/l2/l2_input.h> - -gbp_learn_main_t gbp_learn_main; - -void -gbp_learn_enable (u32 sw_if_index) -{ - vnet_feature_enable_disable ("ip4-unicast", - "gbp-learn-ip4", sw_if_index, 1, 0, 0); - vnet_feature_enable_disable ("ip6-unicast", - "gbp-learn-ip6", sw_if_index, 1, 0, 0); -} - -void -gbp_learn_disable (u32 sw_if_index) -{ - vnet_feature_enable_disable ("ip4-unicast", - "gbp-learn-ip4", sw_if_index, 0, 0, 0); - vnet_feature_enable_disable ("ip6-unicast", - "gbp-learn-ip6", sw_if_index, 0, 0, 0); -} - -static clib_error_t * -gbp_learn_init (vlib_main_t * vm) -{ - gbp_learn_main_t *glm = &gbp_learn_main; - vlib_thread_main_t *tm = &vlib_thread_main; - - vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "gbp-learn-l2"); - - /* Initialize the feature next-node indices */ - feat_bitmap_init_next_nodes (vm, - node->index, - L2INPUT_N_FEAT, - l2input_get_feat_names (), - glm->gl_l2_input_feat_next); - - throttle_init (&glm->gl_l2_throttle, - tm->n_vlib_mains, GBP_ENDPOINT_HASH_LEARN_RATE); - - throttle_init (&glm->gl_l3_throttle, - tm->n_vlib_mains, GBP_ENDPOINT_HASH_LEARN_RATE); - - glm->gl_logger = vlib_log_register_class ("gbp", "learn"); - - return 0; -} - -VLIB_INIT_FUNCTION (gbp_learn_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_learn.h b/src/plugins/gbp/gbp_learn.h deleted file mode 100644 index b4f3ae0a23d..00000000000 --- a/src/plugins/gbp/gbp_learn.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_LEARN_H__ -#define __GBP_LEARN_H__ - -#include <plugins/gbp/gbp.h> - -#include <vnet/util/throttle.h> - -/** - * The maximum learning rate per-hashed EP - */ -#define GBP_ENDPOINT_HASH_LEARN_RATE (1e-2) - -/** - * Grouping of global data for the GBP source EPG classification feature - */ -typedef struct gbp_learn_main_t_ -{ - /** - * Next nodes for L2 output features - */ - u32 gl_l2_input_feat_next[32]; - - /** - * logger - VLIB log class - */ - vlib_log_class_t gl_logger; - - /** - * throttles for the DP leanring - */ - throttle_t gl_l2_throttle; - throttle_t gl_l3_throttle; -} gbp_learn_main_t; - -extern gbp_learn_main_t gbp_learn_main; - -extern void gbp_learn_enable (u32 sw_if_index); -extern void gbp_learn_disable (u32 sw_if_index); - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_learn_node.c b/src/plugins/gbp/gbp_learn_node.c deleted file mode 100644 index a6c54971956..00000000000 --- a/src/plugins/gbp/gbp_learn_node.c +++ /dev/null @@ -1,718 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp.h> -#include <plugins/gbp/gbp_learn.h> -#include <plugins/gbp/gbp_bridge_domain.h> -#include <vlibmemory/api.h> - -#include <vnet/util/throttle.h> -#include <vnet/l2/l2_input.h> -#include <vnet/fib/fib_table.h> -#include <vnet/vxlan-gbp/vxlan_gbp_packet.h> -#include <vnet/ethernet/arp_packet.h> - -#define GBP_LEARN_DBG(...) \ - vlib_log_debug (gbp_learn_main.gl_logger, __VA_ARGS__); - -#define foreach_gbp_learn \ - _(DROP, "drop") - -typedef enum -{ -#define _(sym,str) GBP_LEARN_ERROR_##sym, - foreach_gbp_learn -#undef _ - GBP_LEARN_N_ERROR, -} gbp_learn_error_t; - -static char *gbp_learn_error_strings[] = { -#define _(sym,string) string, - foreach_gbp_learn -#undef _ -}; - -typedef enum -{ -#define _(sym,str) GBP_LEARN_NEXT_##sym, - foreach_gbp_learn -#undef _ - GBP_LEARN_N_NEXT, -} gbp_learn_next_t; - -typedef struct gbp_learn_l2_t_ -{ - ip46_address_t ip; - mac_address_t mac; - u32 sw_if_index; - u32 bd_index; - sclass_t sclass; - ip46_address_t outer_src; - ip46_address_t outer_dst; -} gbp_learn_l2_t; - - -static void -gbp_learn_l2_cp (const gbp_learn_l2_t * gl2) -{ - ip46_address_t *ips = NULL; - - GBP_LEARN_DBG ("L2 EP: %U %U, %d", - format_mac_address_t, &gl2->mac, - format_ip46_address, &gl2->ip, IP46_TYPE_ANY, gl2->sclass); - - if (!ip46_address_is_zero (&gl2->ip)) - vec_add1 (ips, gl2->ip); - - /* - * flip the source and dst, since that's how it was received, this API - * takes how it's sent - */ - gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_DP, - gl2->sw_if_index, ips, - &gl2->mac, INDEX_INVALID, - INDEX_INVALID, gl2->sclass, - (GBP_ENDPOINT_FLAG_LEARNT | - GBP_ENDPOINT_FLAG_REMOTE), - &gl2->outer_dst, &gl2->outer_src, NULL); - vec_free (ips); -} - -static void -gbp_learn_l2_ip4_dp (const u8 * mac, const ip4_address_t * ip, - u32 bd_index, u32 sw_if_index, sclass_t sclass, - const ip4_address_t * outer_src, - const ip4_address_t * outer_dst) -{ - gbp_learn_l2_t gl2 = { - .sw_if_index = sw_if_index, - .bd_index = bd_index, - .sclass = sclass, - .ip.ip4 = *ip, - .outer_src.ip4 = *outer_src, - .outer_dst.ip4 = *outer_dst, - }; - mac_address_from_bytes (&gl2.mac, mac); - - vl_api_rpc_call_main_thread (gbp_learn_l2_cp, (u8 *) & gl2, sizeof (gl2)); -} - -static void -gbp_learn_l2_ip6_dp (const u8 * mac, const ip6_address_t * ip, - u32 bd_index, u32 sw_if_index, sclass_t sclass, - const ip4_address_t * outer_src, - const ip4_address_t * outer_dst) -{ - gbp_learn_l2_t gl2 = { - .sw_if_index = sw_if_index, - .bd_index = bd_index, - .sclass = sclass, - .ip.ip6 = *ip, - .outer_src.ip4 = *outer_src, - .outer_dst.ip4 = *outer_dst, - }; - mac_address_from_bytes (&gl2.mac, mac); - - vl_api_rpc_call_main_thread (gbp_learn_l2_cp, (u8 *) & gl2, sizeof (gl2)); -} - -static void -gbp_learn_l2_dp (const u8 * mac, u32 bd_index, u32 sw_if_index, - sclass_t sclass, - const ip4_address_t * outer_src, - const ip4_address_t * outer_dst) -{ - gbp_learn_l2_t gl2 = { - .sw_if_index = sw_if_index, - .bd_index = bd_index, - .sclass = sclass, - .outer_src.ip4 = *outer_src, - .outer_dst.ip4 = *outer_dst, - }; - mac_address_from_bytes (&gl2.mac, mac); - - vl_api_rpc_call_main_thread (gbp_learn_l2_cp, (u8 *) & gl2, sizeof (gl2)); -} - -/** - * per-packet trace data - */ -typedef struct gbp_learn_l2_trace_t_ -{ - /* per-pkt trace data */ - mac_address_t mac; - u32 sw_if_index; - u32 new; - u32 throttled; - u32 sclass; - u32 d_bit; - gbp_bridge_domain_flags_t gb_flags; -} gbp_learn_l2_trace_t; - -always_inline void -gbp_learn_get_outer (const ethernet_header_t * eh0, - ip4_address_t * outer_src, ip4_address_t * outer_dst) -{ - ip4_header_t *ip0; - u8 *buff; - - /* rewind back to the ivxlan header */ - buff = (u8 *) eh0; - buff -= (sizeof (vxlan_gbp_header_t) + - sizeof (udp_header_t) + sizeof (ip4_header_t)); - - ip0 = (ip4_header_t *) buff; - - *outer_src = ip0->src_address; - *outer_dst = ip0->dst_address; -} - -always_inline int -gbp_endpoint_update_required (const gbp_endpoint_t * ge0, - u32 rx_sw_if_index, sclass_t sclass) -{ - /* Conditions for [re]learning this EP */ - - /* 1. it doesn't have a dataplane source */ - if (!gbp_endpoint_is_learnt (ge0)) - return (!0); - - /* 2. has the input interface changed */ - if (gbp_itf_get_sw_if_index (ge0->ge_fwd.gef_itf) != rx_sw_if_index) - return (!0); - - /* 3. has the sclass changed */ - if (sclass != ge0->ge_fwd.gef_sclass) - return (!0); - - /* otherwise it's unchanged */ - return (0); -} - -VLIB_NODE_FN (gbp_learn_l2_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next, next_index, thread_index, seed; - gbp_learn_main_t *glm; - f64 time_now; - - glm = &gbp_learn_main; - next_index = 0; - n_left_from = frame->n_vectors; - from = vlib_frame_vector_args (frame); - time_now = vlib_time_now (vm); - thread_index = vm->thread_index; - - seed = throttle_seed (&glm->gl_l2_throttle, thread_index, time_now); - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - ip4_address_t outer_src, outer_dst; - const ethernet_header_t *eh0; - u32 bi0, sw_if_index0, t0; - gbp_bridge_domain_t *gb0; - gbp_learn_next_t next0; - gbp_endpoint_t *ge0; - vlib_buffer_t *b0; - sclass_t sclass0; - - next0 = GBP_LEARN_NEXT_DROP; - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - - eh0 = vlib_buffer_get_current (b0); - sclass0 = vnet_buffer2 (b0)->gbp.sclass; - - next0 = vnet_l2_feature_next (b0, glm->gl_l2_input_feat_next, - L2INPUT_FEAT_GBP_LEARN); - - ge0 = gbp_endpoint_find_mac (eh0->src_address, - vnet_buffer (b0)->l2.bd_index); - gb0 = - gbp_bridge_domain_get_by_bd_index (vnet_buffer (b0)->l2.bd_index); - - if ((vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_D) || - (gb0->gb_flags & GBP_BD_FLAG_DO_NOT_LEARN)) - { - t0 = 1; - goto trace; - } - - /* - * check for new EP or a moved EP - */ - if (NULL == ge0 || - gbp_endpoint_update_required (ge0, sw_if_index0, sclass0)) - { - /* - * use the last 4 bytes of the mac address as the hash for the EP - */ - t0 = throttle_check (&glm->gl_l2_throttle, thread_index, - *((u32 *) (eh0->src_address + 2)), seed); - if (!t0) - { - gbp_learn_get_outer (eh0, &outer_src, &outer_dst); - - if (outer_src.as_u32 == 0 || outer_dst.as_u32 == 0) - { - t0 = 2; - goto trace; - } - - switch (clib_net_to_host_u16 (eh0->type)) - { - case ETHERNET_TYPE_IP4: - { - const ip4_header_t *ip0; - - ip0 = (ip4_header_t *) (eh0 + 1); - - gbp_learn_l2_ip4_dp (eh0->src_address, - &ip0->src_address, - vnet_buffer (b0)->l2.bd_index, - sw_if_index0, sclass0, - &outer_src, &outer_dst); - - break; - } - case ETHERNET_TYPE_IP6: - { - const ip6_header_t *ip0; - - ip0 = (ip6_header_t *) (eh0 + 1); - - gbp_learn_l2_ip6_dp (eh0->src_address, - &ip0->src_address, - vnet_buffer (b0)->l2.bd_index, - sw_if_index0, sclass0, - &outer_src, &outer_dst); - - break; - } - case ETHERNET_TYPE_ARP: - { - const ethernet_arp_header_t *arp0; - - arp0 = (ethernet_arp_header_t *) (eh0 + 1); - - gbp_learn_l2_ip4_dp (eh0->src_address, - &arp0->ip4_over_ethernet[0].ip4, - vnet_buffer (b0)->l2.bd_index, - sw_if_index0, sclass0, - &outer_src, &outer_dst); - break; - } - default: - gbp_learn_l2_dp (eh0->src_address, - vnet_buffer (b0)->l2.bd_index, - sw_if_index0, sclass0, - &outer_src, &outer_dst); - break; - } - } - } - else - { - /* - * this update could happen simultaneoulsy from multiple workers - * but that's ok we are not interested in being very accurate. - */ - t0 = 0; - ge0->ge_last_time = time_now; - } - trace: - if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_IS_TRACED))) - { - gbp_learn_l2_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - clib_memcpy_fast (t->mac.bytes, eh0->src_address, 6); - t->new = (NULL == ge0); - t->throttled = t0; - t->sw_if_index = sw_if_index0; - t->sclass = sclass0; - t->gb_flags = gb0->gb_flags; - t->d_bit = ! !(vnet_buffer2 (b0)->gbp.flags & - VXLAN_GBP_GPFLAGS_D); - } - - /* verify speculative enqueue, maybe switch current next frame */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - -/* packet trace format function */ -static u8 * -format_gbp_learn_l2_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - gbp_learn_l2_trace_t *t = va_arg (*args, gbp_learn_l2_trace_t *); - - s = format (s, "new:%d throttled:%d d-bit:%d mac:%U itf:%d sclass:%d" - " gb-flags:%U", - t->new, t->throttled, t->d_bit, - format_mac_address_t, &t->mac, t->sw_if_index, t->sclass, - format_gbp_bridge_domain_flags, t->gb_flags); - - return s; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (gbp_learn_l2_node) = { - .name = "gbp-learn-l2", - .vector_size = sizeof (u32), - .format_trace = format_gbp_learn_l2_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(gbp_learn_error_strings), - .error_strings = gbp_learn_error_strings, - - .n_next_nodes = GBP_LEARN_N_NEXT, - - .next_nodes = { - [GBP_LEARN_NEXT_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -typedef struct gbp_learn_l3_t_ -{ - ip46_address_t ip; - u32 fib_index; - u32 sw_if_index; - sclass_t sclass; - ip46_address_t outer_src; - ip46_address_t outer_dst; -} gbp_learn_l3_t; - -static void -gbp_learn_l3_cp (const gbp_learn_l3_t * gl3) -{ - ip46_address_t *ips = NULL; - - GBP_LEARN_DBG ("L3 EP: %U, %d", format_ip46_address, &gl3->ip, - IP46_TYPE_ANY, gl3->sclass); - - vec_add1 (ips, gl3->ip); - - gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_DP, - gl3->sw_if_index, ips, NULL, - INDEX_INVALID, INDEX_INVALID, gl3->sclass, - (GBP_ENDPOINT_FLAG_REMOTE | - GBP_ENDPOINT_FLAG_LEARNT), - &gl3->outer_dst, &gl3->outer_src, NULL); - vec_free (ips); -} - -static void -gbp_learn_ip4_dp (const ip4_address_t * ip, - u32 fib_index, u32 sw_if_index, sclass_t sclass, - const ip4_address_t * outer_src, - const ip4_address_t * outer_dst) -{ - /* *INDENT-OFF* */ - gbp_learn_l3_t gl3 = { - .ip = { - .ip4 = *ip, - }, - .sw_if_index = sw_if_index, - .fib_index = fib_index, - .sclass = sclass, - .outer_src.ip4 = *outer_src, - .outer_dst.ip4 = *outer_dst, - }; - /* *INDENT-ON* */ - - vl_api_rpc_call_main_thread (gbp_learn_l3_cp, (u8 *) & gl3, sizeof (gl3)); -} - -static void -gbp_learn_ip6_dp (const ip6_address_t * ip, - u32 fib_index, u32 sw_if_index, sclass_t sclass, - const ip4_address_t * outer_src, - const ip4_address_t * outer_dst) -{ - /* *INDENT-OFF* */ - gbp_learn_l3_t gl3 = { - .ip = { - .ip6 = *ip, - }, - .sw_if_index = sw_if_index, - .fib_index = fib_index, - .sclass = sclass, - .outer_src.ip4 = *outer_src, - .outer_dst.ip4 = *outer_dst, - }; - /* *INDENT-ON* */ - - vl_api_rpc_call_main_thread (gbp_learn_l3_cp, (u8 *) & gl3, sizeof (gl3)); -} - -/** - * per-packet trace data - */ -typedef struct gbp_learn_l3_trace_t_ -{ - /* per-pkt trace data */ - ip46_address_t ip; - u32 sw_if_index; - u32 new; - u32 throttled; - u32 sclass; -} gbp_learn_l3_trace_t; - -static uword -gbp_learn_l3 (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame, - fib_protocol_t fproto) -{ - u32 n_left_from, *from, *to_next, next_index, thread_index, seed; - gbp_learn_main_t *glm; - f64 time_now; - - glm = &gbp_learn_main; - next_index = 0; - n_left_from = frame->n_vectors; - from = vlib_frame_vector_args (frame); - time_now = vlib_time_now (vm); - thread_index = vm->thread_index; - - seed = throttle_seed (&glm->gl_l3_throttle, thread_index, time_now); - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - CLIB_UNUSED (const ip4_header_t *) ip4_0; - CLIB_UNUSED (const ip6_header_t *) ip6_0; - u32 bi0, sw_if_index0, t0, fib_index0; - ip4_address_t outer_src, outer_dst; - ethernet_header_t *eth0; - gbp_learn_next_t next0; - gbp_endpoint_t *ge0; - vlib_buffer_t *b0; - sclass_t sclass0; - - next0 = GBP_LEARN_NEXT_DROP; - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - sclass0 = vnet_buffer2 (b0)->gbp.sclass; - ip6_0 = NULL; - ip4_0 = NULL; - - vnet_feature_next (&next0, b0); - - if (vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_D) - { - t0 = 1; - ge0 = NULL; - goto trace; - } - - fib_index0 = fib_table_get_index_for_sw_if_index (fproto, - sw_if_index0); - - if (FIB_PROTOCOL_IP6 == fproto) - { - ip6_0 = vlib_buffer_get_current (b0); - eth0 = (ethernet_header_t *) (((u8 *) ip6_0) - sizeof (*eth0)); - - gbp_learn_get_outer (eth0, &outer_src, &outer_dst); - - ge0 = gbp_endpoint_find_ip6 (&ip6_0->src_address, fib_index0); - - if ((NULL == ge0) || - gbp_endpoint_update_required (ge0, sw_if_index0, sclass0)) - { - t0 = throttle_check (&glm->gl_l3_throttle, - thread_index, - ip6_address_hash_to_u32 - (&ip6_0->src_address), seed); - - if (!t0) - { - gbp_learn_ip6_dp (&ip6_0->src_address, - fib_index0, sw_if_index0, sclass0, - &outer_src, &outer_dst); - } - } - else - { - /* - * this update could happen simultaneoulsy from multiple - * workers but that's ok we are not interested in being - * very accurate. - */ - t0 = 0; - ge0->ge_last_time = time_now; - } - } - else - { - ip4_0 = vlib_buffer_get_current (b0); - eth0 = (ethernet_header_t *) (((u8 *) ip4_0) - sizeof (*eth0)); - - gbp_learn_get_outer (eth0, &outer_src, &outer_dst); - ge0 = gbp_endpoint_find_ip4 (&ip4_0->src_address, fib_index0); - - if ((NULL == ge0) || - gbp_endpoint_update_required (ge0, sw_if_index0, sclass0)) - { - t0 = throttle_check (&glm->gl_l3_throttle, thread_index, - ip4_0->src_address.as_u32, seed); - - if (!t0) - { - gbp_learn_ip4_dp (&ip4_0->src_address, - fib_index0, sw_if_index0, sclass0, - &outer_src, &outer_dst); - } - } - else - { - /* - * this update could happen simultaneoulsy from multiple - * workers but that's ok we are not interested in being - * very accurate. - */ - t0 = 0; - ge0->ge_last_time = time_now; - } - } - trace: - if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_IS_TRACED))) - { - gbp_learn_l3_trace_t *t; - - t = vlib_add_trace (vm, node, b0, sizeof (*t)); - if (FIB_PROTOCOL_IP6 == fproto && ip6_0) - ip46_address_set_ip6 (&t->ip, &ip6_0->src_address); - if (FIB_PROTOCOL_IP4 == fproto && ip4_0) - ip46_address_set_ip4 (&t->ip, &ip4_0->src_address); - t->new = (NULL == ge0); - t->throttled = t0; - t->sw_if_index = sw_if_index0; - t->sclass = sclass0; - } - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - -/* packet trace format function */ -static u8 * -format_gbp_learn_l3_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - gbp_learn_l3_trace_t *t = va_arg (*args, gbp_learn_l3_trace_t *); - - s = format (s, "new:%d throttled:%d ip:%U itf:%d sclass:%d", - t->new, t->throttled, - format_ip46_address, &t->ip, IP46_TYPE_ANY, t->sw_if_index, - t->sclass); - - return s; -} - -VLIB_NODE_FN (gbp_learn_ip4_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_learn_l3 (vm, node, frame, FIB_PROTOCOL_IP4)); -} - -VLIB_NODE_FN (gbp_learn_ip6_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_learn_l3 (vm, node, frame, FIB_PROTOCOL_IP6)); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (gbp_learn_ip4_node) = { - .name = "gbp-learn-ip4", - .vector_size = sizeof (u32), - .format_trace = format_gbp_learn_l3_trace, - .type = VLIB_NODE_TYPE_INTERNAL, -}; - -VNET_FEATURE_INIT (gbp_learn_ip4, static) = -{ - .arc_name = "ip4-unicast", - .node_name = "gbp-learn-ip4", -}; - -VLIB_REGISTER_NODE (gbp_learn_ip6_node) = { - .name = "gbp-learn-ip6", - .vector_size = sizeof (u32), - .format_trace = format_gbp_learn_l3_trace, - .type = VLIB_NODE_TYPE_INTERNAL, -}; - -VNET_FEATURE_INIT (gbp_learn_ip6, static) = -{ - .arc_name = "ip6-unicast", - .node_name = "gbp-learn-ip6", -}; - -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_policy.c b/src/plugins/gbp/gbp_policy.c deleted file mode 100644 index 127c6d3f059..00000000000 --- a/src/plugins/gbp/gbp_policy.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp.h> -#include <plugins/gbp/gbp_policy.h> -#include <vnet/vxlan-gbp/vxlan_gbp_packet.h> - -gbp_policy_main_t gbp_policy_main; - -/* packet trace format function */ -u8 * -format_gbp_policy_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - gbp_policy_trace_t *t = va_arg (*args, gbp_policy_trace_t *); - - s = - format (s, - "scope:%d sclass:%d, dclass:%d, action:%U flags:%U acl: %d rule: %d", - t->scope, t->sclass, t->dclass, format_gbp_rule_action, t->action, - format_vxlan_gbp_header_gpflags, t->flags, t->acl_match, - t->rule_match); - - return s; -} - -static clib_error_t * -gbp_policy_init (vlib_main_t * vm) -{ - gbp_policy_main_t *gpm = &gbp_policy_main; - clib_error_t *error = 0; - - /* Initialize the feature next-node indexes */ - vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "gbp-policy-port"); - feat_bitmap_init_next_nodes (vm, - node->index, - L2OUTPUT_N_FEAT, - l2output_get_feat_names (), - gpm->l2_output_feat_next[GBP_POLICY_PORT]); - - node = vlib_get_node_by_name (vm, (u8 *) "gbp-policy-mac"); - feat_bitmap_init_next_nodes (vm, - node->index, - L2OUTPUT_N_FEAT, - l2output_get_feat_names (), - gpm->l2_output_feat_next[GBP_POLICY_MAC]); - - node = vlib_get_node_by_name (vm, (u8 *) "gbp-policy-lpm"); - feat_bitmap_init_next_nodes (vm, - node->index, - L2OUTPUT_N_FEAT, - l2output_get_feat_names (), - gpm->l2_output_feat_next[GBP_POLICY_LPM]); - - return error; -} - -VLIB_INIT_FUNCTION (gbp_policy_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_policy.h b/src/plugins/gbp/gbp_policy.h deleted file mode 100644 index 6f87f2ec7c4..00000000000 --- a/src/plugins/gbp/gbp_policy.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_POLICY_H__ -#define __GBP_POLICY_H__ - -#include <plugins/gbp/gbp_contract.h> - -/** - * per-packet trace data - */ -typedef struct gbp_policy_trace_t_ -{ - /* per-pkt trace data */ - gbp_scope_t scope; - sclass_t sclass; - sclass_t dclass; - gbp_rule_action_t action; - u32 flags; - u32 acl_match; - u32 rule_match; -} gbp_policy_trace_t; - -/* packet trace format function */ -u8 * format_gbp_policy_trace (u8 * s, va_list * args); - -static_always_inline void -gbp_policy_trace(vlib_main_t * vm, vlib_node_runtime_t * node, vlib_buffer_t *b, const gbp_contract_key_t *key, gbp_rule_action_t action, u32 acl_match, u32 rule_match) -{ - gbp_policy_trace_t *t; - - if (PREDICT_TRUE (!(b->flags & VLIB_BUFFER_IS_TRACED))) - return; - - t = vlib_add_trace (vm, node, b, sizeof (*t)); - t->sclass = key->gck_src; - t->dclass = key->gck_dst; - t->scope = key->gck_scope; - t->action = action; - t->flags = vnet_buffer2 (b)->gbp.flags; - t->acl_match = acl_match; - t->rule_match = rule_match; -} - -#endif /* __GBP_POLICY_H__ */ diff --git a/src/plugins/gbp/gbp_policy_dpo.c b/src/plugins/gbp/gbp_policy_dpo.c deleted file mode 100644 index 9f26b9c67ab..00000000000 --- a/src/plugins/gbp/gbp_policy_dpo.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <vnet/dpo/dvr_dpo.h> -#include <vnet/dpo/drop_dpo.h> -#include <vnet/vxlan-gbp/vxlan_gbp_packet.h> -#include <vnet/vxlan-gbp/vxlan_gbp.h> - -#include <plugins/gbp/gbp.h> -#include <plugins/gbp/gbp_policy.h> -#include <plugins/gbp/gbp_policy_dpo.h> -#include <plugins/gbp/gbp_recirc.h> -#include <plugins/gbp/gbp_contract.h> - -#ifndef CLIB_MARCH_VARIANT -/** - * DPO pool - */ -gbp_policy_dpo_t *gbp_policy_dpo_pool; - -/** - * DPO type registered for these GBP FWD - */ -dpo_type_t gbp_policy_dpo_type; - -static gbp_policy_dpo_t * -gbp_policy_dpo_alloc (void) -{ - gbp_policy_dpo_t *gpd; - - pool_get_aligned_zero (gbp_policy_dpo_pool, gpd, CLIB_CACHE_LINE_BYTES); - - return (gpd); -} - -static inline gbp_policy_dpo_t * -gbp_policy_dpo_get_from_dpo (const dpo_id_t * dpo) -{ - ASSERT (gbp_policy_dpo_type == dpo->dpoi_type); - - return (gbp_policy_dpo_get (dpo->dpoi_index)); -} - -static inline index_t -gbp_policy_dpo_get_index (gbp_policy_dpo_t * gpd) -{ - return (gpd - gbp_policy_dpo_pool); -} - -static void -gbp_policy_dpo_lock (dpo_id_t * dpo) -{ - gbp_policy_dpo_t *gpd; - - gpd = gbp_policy_dpo_get_from_dpo (dpo); - gpd->gpd_locks++; -} - -static void -gbp_policy_dpo_unlock (dpo_id_t * dpo) -{ - gbp_policy_dpo_t *gpd; - - gpd = gbp_policy_dpo_get_from_dpo (dpo); - gpd->gpd_locks--; - - if (0 == gpd->gpd_locks) - { - dpo_reset (&gpd->gpd_dpo); - pool_put (gbp_policy_dpo_pool, gpd); - } -} - -static u32 -gbp_policy_dpo_get_urpf (const dpo_id_t * dpo) -{ - gbp_policy_dpo_t *gpd; - - gpd = gbp_policy_dpo_get_from_dpo (dpo); - - return (gpd->gpd_sw_if_index); -} - -void -gbp_policy_dpo_add_or_lock (dpo_proto_t dproto, - gbp_scope_t scope, - sclass_t sclass, u32 sw_if_index, dpo_id_t * dpo) -{ - gbp_policy_dpo_t *gpd; - dpo_id_t parent = DPO_INVALID; - - gpd = gbp_policy_dpo_alloc (); - - gpd->gpd_proto = dproto; - gpd->gpd_sw_if_index = sw_if_index; - gpd->gpd_sclass = sclass; - gpd->gpd_scope = scope; - - if (~0 != sw_if_index) - { - /* - * stack on the DVR DPO for the output interface - */ - dvr_dpo_add_or_lock (sw_if_index, dproto, &parent); - } - else - { - dpo_copy (&parent, drop_dpo_get (dproto)); - } - - dpo_stack (gbp_policy_dpo_type, dproto, &gpd->gpd_dpo, &parent); - dpo_set (dpo, gbp_policy_dpo_type, dproto, gbp_policy_dpo_get_index (gpd)); -} - -u8 * -format_gbp_policy_dpo (u8 * s, va_list * ap) -{ - index_t index = va_arg (*ap, index_t); - u32 indent = va_arg (*ap, u32); - gbp_policy_dpo_t *gpd = gbp_policy_dpo_get (index); - vnet_main_t *vnm = vnet_get_main (); - - s = format (s, "gbp-policy-dpo: %U, scope:%d sclass:%d out:%U", - format_dpo_proto, gpd->gpd_proto, - gpd->gpd_scope, (int) gpd->gpd_sclass, - format_vnet_sw_if_index_name, vnm, gpd->gpd_sw_if_index); - s = format (s, "\n%U", format_white_space, indent + 2); - s = format (s, "%U", format_dpo_id, &gpd->gpd_dpo, indent + 4); - - return (s); -} - -/** - * Interpose a policy DPO - */ -static void -gbp_policy_dpo_interpose (const dpo_id_t * original, - const dpo_id_t * parent, dpo_id_t * clone) -{ - gbp_policy_dpo_t *gpd, *gpd_clone; - - gpd_clone = gbp_policy_dpo_alloc (); - gpd = gbp_policy_dpo_get (original->dpoi_index); - - gpd_clone->gpd_proto = gpd->gpd_proto; - gpd_clone->gpd_scope = gpd->gpd_scope; - gpd_clone->gpd_sclass = gpd->gpd_sclass; - gpd_clone->gpd_sw_if_index = gpd->gpd_sw_if_index; - - /* - * if no interface is provided, grab one from the parent - * on which we stack - */ - if (~0 == gpd_clone->gpd_sw_if_index) - gpd_clone->gpd_sw_if_index = dpo_get_urpf (parent); - - dpo_stack (gbp_policy_dpo_type, - gpd_clone->gpd_proto, &gpd_clone->gpd_dpo, parent); - - dpo_set (clone, - gbp_policy_dpo_type, - gpd_clone->gpd_proto, gbp_policy_dpo_get_index (gpd_clone)); -} - -const static dpo_vft_t gbp_policy_dpo_vft = { - .dv_lock = gbp_policy_dpo_lock, - .dv_unlock = gbp_policy_dpo_unlock, - .dv_format = format_gbp_policy_dpo, - .dv_get_urpf = gbp_policy_dpo_get_urpf, - .dv_mk_interpose = gbp_policy_dpo_interpose, -}; - -/** - * @brief The per-protocol VLIB graph nodes that are assigned to a glean - * object. - * - * this means that these graph nodes are ones from which a glean is the - * parent object in the DPO-graph. - */ -const static char *const gbp_policy_dpo_ip4_nodes[] = { - "ip4-gbp-policy-dpo", - NULL, -}; - -const static char *const gbp_policy_dpo_ip6_nodes[] = { - "ip6-gbp-policy-dpo", - NULL, -}; - -const static char *const *const gbp_policy_dpo_nodes[DPO_PROTO_NUM] = { - [DPO_PROTO_IP4] = gbp_policy_dpo_ip4_nodes, - [DPO_PROTO_IP6] = gbp_policy_dpo_ip6_nodes, -}; - -dpo_type_t -gbp_policy_dpo_get_type (void) -{ - return (gbp_policy_dpo_type); -} - -static clib_error_t * -gbp_policy_dpo_module_init (vlib_main_t * vm) -{ - gbp_policy_dpo_type = dpo_register_new_type (&gbp_policy_dpo_vft, - gbp_policy_dpo_nodes); - - return (NULL); -} - -VLIB_INIT_FUNCTION (gbp_policy_dpo_module_init); -#endif /* CLIB_MARCH_VARIANT */ - -typedef enum -{ - GBP_POLICY_DROP, - GBP_POLICY_N_NEXT, -} gbp_policy_next_t; - -always_inline u32 -gbp_rule_l3_redirect (const gbp_rule_t * gu, vlib_buffer_t * b0, int is_ip6) -{ - gbp_policy_node_t pnode; - const dpo_id_t *dpo; - dpo_proto_t dproto; - - pnode = (is_ip6 ? GBP_POLICY_NODE_IP6 : GBP_POLICY_NODE_IP4); - dproto = (is_ip6 ? DPO_PROTO_IP6 : DPO_PROTO_IP4); - dpo = &gu->gu_dpo[pnode][dproto]; - - /* The flow hash is still valid as this is a IP packet being switched */ - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo->dpoi_index; - - return (dpo->dpoi_next_node); -} - -always_inline uword -gbp_policy_dpo_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame, u8 is_ip6) -{ - gbp_main_t *gm = &gbp_main; - u32 n_left_from, next_index, *from, *to_next; - u32 n_allow_intra, n_allow_a_bit, n_allow_sclass_1; - - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - n_allow_intra = n_allow_a_bit = n_allow_sclass_1 = 0; - - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - gbp_rule_action_t action0 = GBP_RULE_DENY; - u32 acl_match = ~0, rule_match = ~0; - const gbp_policy_dpo_t *gpd0; - gbp_contract_error_t err0; - gbp_contract_key_t key0; - vlib_buffer_t *b0; - gbp_rule_t *rule0; - u32 bi0, next0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - next0 = GBP_POLICY_DROP; - - b0 = vlib_get_buffer (vm, bi0); - - gpd0 = gbp_policy_dpo_get (vnet_buffer (b0)->ip.adj_index[VLIB_TX]); - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = gpd0->gpd_dpo.dpoi_index; - - /* - * Reflection check; in and out on an ivxlan tunnel - */ - if ((~0 != vxlan_gbp_tunnel_by_sw_if_index (gpd0->gpd_sw_if_index)) - && (vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_R)) - { - goto trace; - } - - if (vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_A) - { - next0 = gpd0->gpd_dpo.dpoi_next_node; - key0.as_u64 = ~0; - n_allow_a_bit++; - goto trace; - } - - /* zero out the key to ensure the pad space is clear */ - key0.as_u64 = 0; - key0.gck_src = vnet_buffer2 (b0)->gbp.sclass; - - if (SCLASS_INVALID == key0.gck_src) - { - /* - * the src EPG is not set when the packet arrives on an EPG - * uplink interface and we do not need to apply policy - */ - next0 = gpd0->gpd_dpo.dpoi_next_node; - goto trace; - } - - key0.gck_scope = gpd0->gpd_scope; - key0.gck_dst = gpd0->gpd_sclass; - - action0 = - gbp_contract_apply (vm, gm, &key0, b0, &rule0, &n_allow_intra, - &n_allow_sclass_1, &acl_match, &rule_match, - &err0, - is_ip6 ? GBP_CONTRACT_APPLY_IP6 : - GBP_CONTRACT_APPLY_IP4); - switch (action0) - { - case GBP_RULE_PERMIT: - next0 = gpd0->gpd_dpo.dpoi_next_node; - vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A; - break; - case GBP_RULE_REDIRECT: - next0 = gbp_rule_l3_redirect (rule0, b0, is_ip6); - vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A; - break; - case GBP_RULE_DENY: - next0 = GBP_POLICY_DROP; - b0->error = node->errors[err0]; - break; - } - - trace: - gbp_policy_trace (vm, node, b0, &key0, action0, acl_match, - rule_match); - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, next0); - } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - GBP_CONTRACT_ERROR_ALLOW_INTRA, n_allow_intra); - vlib_node_increment_counter (vm, node->node_index, - GBP_CONTRACT_ERROR_ALLOW_A_BIT, n_allow_a_bit); - vlib_node_increment_counter (vm, node->node_index, - GBP_CONTRACT_ERROR_ALLOW_SCLASS_1, - n_allow_sclass_1); - return from_frame->n_vectors; -} - -VLIB_NODE_FN (ip4_gbp_policy_dpo_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - return (gbp_policy_dpo_inline (vm, node, from_frame, 0)); -} - -VLIB_NODE_FN (ip6_gbp_policy_dpo_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - return (gbp_policy_dpo_inline (vm, node, from_frame, 1)); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (ip4_gbp_policy_dpo_node) = { - .name = "ip4-gbp-policy-dpo", - .vector_size = sizeof (u32), - .format_trace = format_gbp_policy_trace, - - .n_errors = ARRAY_LEN(gbp_contract_error_strings), - .error_strings = gbp_contract_error_strings, - - .n_next_nodes = GBP_POLICY_N_NEXT, - .next_nodes = - { - [GBP_POLICY_DROP] = "ip4-drop", - } -}; -VLIB_REGISTER_NODE (ip6_gbp_policy_dpo_node) = { - .name = "ip6-gbp-policy-dpo", - .vector_size = sizeof (u32), - .format_trace = format_gbp_policy_trace, - - .n_errors = ARRAY_LEN(gbp_contract_error_strings), - .error_strings = gbp_contract_error_strings, - - .n_next_nodes = GBP_POLICY_N_NEXT, - .next_nodes = - { - [GBP_POLICY_DROP] = "ip6-drop", - } -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_policy_dpo.h b/src/plugins/gbp/gbp_policy_dpo.h deleted file mode 100644 index 77ca5d93bd0..00000000000 --- a/src/plugins/gbp/gbp_policy_dpo.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_POLICY_DPO_H__ -#define __GBP_POLICY_DPO_H__ - -#include <vnet/dpo/dpo.h> -#include <vnet/dpo/load_balance.h> -#include <vnet/fib/ip4_fib.h> -#include <vnet/fib/ip6_fib.h> - -/** - * @brief - * The GBP FWD DPO. Used in the L3 path to select the correct EPG uplink - * based on the source EPG. - */ -typedef struct gbp_policy_dpo_t_ -{ - CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); - - /** - * The protocol of packets using this DPO - */ - dpo_proto_t gpd_proto; - - /** - * SClass - */ - sclass_t gpd_sclass; - - /** - * sclass scope - */ - gbp_scope_t gpd_scope; - - /** - * output sw_if_index - */ - u32 gpd_sw_if_index; - - /** - * number of locks. - */ - u16 gpd_locks; - - /** - * Stacked DPO on DVR/ADJ of output interface - */ - dpo_id_t gpd_dpo; -} gbp_policy_dpo_t; - -extern void gbp_policy_dpo_add_or_lock (dpo_proto_t dproto, - gbp_scope_t scope, - sclass_t sclass, - u32 sw_if_index, dpo_id_t * dpo); - -extern dpo_type_t gbp_policy_dpo_get_type (void); - -extern vlib_node_registration_t ip4_gbp_policy_dpo_node; -extern vlib_node_registration_t ip6_gbp_policy_dpo_node; -extern vlib_node_registration_t gbp_policy_port_node; - -/** - * Types exposed for the Data-plane - */ -extern dpo_type_t gbp_policy_dpo_type; -extern gbp_policy_dpo_t *gbp_policy_dpo_pool; - -always_inline gbp_policy_dpo_t * -gbp_policy_dpo_get (index_t index) -{ - return (pool_elt_at_index (gbp_policy_dpo_pool, index)); -} - -static_always_inline const gbp_policy_dpo_t * -gbp_classify_get_gpd (const ip4_address_t * ip4, const ip6_address_t * ip6, - const u32 fib_index) -{ - const gbp_policy_dpo_t *gpd; - const dpo_id_t *dpo; - const load_balance_t *lb; - u32 lbi; - - if (ip4) - lbi = ip4_fib_forwarding_lookup (fib_index, ip4); - else if (ip6) - lbi = ip6_fib_table_fwding_lookup (fib_index, ip6); - else - return 0; - - lb = load_balance_get (lbi); - dpo = load_balance_get_bucket_i (lb, 0); - - if (dpo->dpoi_type != gbp_policy_dpo_type) - return 0; - - gpd = gbp_policy_dpo_get (dpo->dpoi_index); - return gpd; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ - -#endif diff --git a/src/plugins/gbp/gbp_policy_node.c b/src/plugins/gbp/gbp_policy_node.c deleted file mode 100644 index 8c6ef5c2b94..00000000000 --- a/src/plugins/gbp/gbp_policy_node.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp.h> -#include <plugins/gbp/gbp_classify.h> -#include <plugins/gbp/gbp_policy.h> -#include <plugins/gbp/gbp_policy_dpo.h> -#include <plugins/gbp/gbp_bridge_domain.h> -#include <plugins/gbp/gbp_ext_itf.h> -#include <plugins/gbp/gbp_contract.h> - -#include <vnet/vxlan-gbp/vxlan_gbp_packet.h> -#include <vnet/vxlan-gbp/vxlan_gbp.h> - -typedef enum -{ - GBP_POLICY_NEXT_DROP, - GBP_POLICY_N_NEXT, -} gbp_policy_next_t; - -always_inline dpo_proto_t -ethertype_to_dpo_proto (u16 etype) -{ - etype = clib_net_to_host_u16 (etype); - - switch (etype) - { - case ETHERNET_TYPE_IP4: - return (DPO_PROTO_IP4); - case ETHERNET_TYPE_IP6: - return (DPO_PROTO_IP6); - } - - return (DPO_PROTO_NONE); -} - -always_inline u32 -gbp_rule_l2_redirect (const gbp_rule_t * gu, vlib_buffer_t * b0) -{ - const ethernet_header_t *eth0; - const dpo_id_t *dpo; - dpo_proto_t dproto; - - eth0 = vlib_buffer_get_current (b0); - /* pop the ethernet header to prepare for L3 rewrite */ - vlib_buffer_advance (b0, vnet_buffer (b0)->l2.l2_len); - - dproto = ethertype_to_dpo_proto (eth0->type); - dpo = &gu->gu_dpo[GBP_POLICY_NODE_L2][dproto]; - - /* save the LB index for the next node and reset the IP flow hash - * so it's recalculated */ - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo->dpoi_index; - vnet_buffer (b0)->ip.flow_hash = 0; - - return (dpo->dpoi_next_node); -} - -static_always_inline gbp_policy_next_t -gbp_policy_l2_feature_next (gbp_policy_main_t * gpm, vlib_buffer_t * b, - const gbp_policy_type_t type) -{ - u32 feat_bit; - - switch (type) - { - case GBP_POLICY_PORT: - feat_bit = L2OUTPUT_FEAT_GBP_POLICY_PORT; - break; - case GBP_POLICY_MAC: - feat_bit = L2OUTPUT_FEAT_GBP_POLICY_MAC; - break; - case GBP_POLICY_LPM: - feat_bit = L2OUTPUT_FEAT_GBP_POLICY_LPM; - break; - default: - return GBP_POLICY_NEXT_DROP; - } - - return vnet_l2_feature_next (b, gpm->l2_output_feat_next[type], feat_bit); -} - -static uword -gbp_policy_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, const gbp_policy_type_t type) -{ - gbp_main_t *gm = &gbp_main; - gbp_policy_main_t *gpm = &gbp_policy_main; - u32 n_left_from, *from, *to_next; - u32 next_index; - u32 n_allow_intra, n_allow_a_bit, n_allow_sclass_1; - - next_index = 0; - n_left_from = frame->n_vectors; - from = vlib_frame_vector_args (frame); - n_allow_intra = n_allow_a_bit = n_allow_sclass_1 = 0; - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - gbp_rule_action_t action0 = GBP_RULE_DENY; - const ethernet_header_t *h0; - const gbp_endpoint_t *ge0; - gbp_contract_error_t err0; - u32 acl_match = ~0, rule_match = ~0; - gbp_policy_next_t next0; - gbp_contract_key_t key0; - u32 bi0, sw_if_index0; - vlib_buffer_t *b0; - gbp_rule_t *rule0; - - next0 = GBP_POLICY_NEXT_DROP; - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - h0 = vlib_buffer_get_current (b0); - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX]; - - /* - * Reflection check; in and out on an ivxlan tunnel - */ - if ((~0 != vxlan_gbp_tunnel_by_sw_if_index (sw_if_index0)) && - (vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_R)) - { - goto trace; - } - - /* - * If the A-bit is set then policy has already been applied - * and we skip enforcement here. - */ - if (vnet_buffer2 (b0)->gbp.flags & VXLAN_GBP_GPFLAGS_A) - { - next0 = gbp_policy_l2_feature_next (gpm, b0, type); - n_allow_a_bit++; - key0.as_u64 = ~0; - goto trace; - } - - /* - * determine the src and dst EPG - */ - - /* zero out the key to ensure the pad space is clear */ - key0.as_u64 = 0; - key0.gck_src = vnet_buffer2 (b0)->gbp.sclass; - key0.gck_dst = SCLASS_INVALID; - - if (GBP_POLICY_LPM == type) - { - const ip4_address_t *ip4 = 0; - const ip6_address_t *ip6 = 0; - const dpo_proto_t proto = - gbp_classify_get_ip_address (h0, &ip4, &ip6, - GBP_CLASSIFY_GET_IP_DST); - if (PREDICT_TRUE (DPO_PROTO_NONE != proto)) - { - const gbp_ext_itf_t *ext_itf = - gbp_ext_itf_get (sw_if_index0); - const gbp_policy_dpo_t *gpd = - gbp_classify_get_gpd (ip4, ip6, - ext_itf->gx_fib_index[proto]); - if (gpd) - key0.gck_dst = gpd->gpd_sclass; - } - } - else - { - if (GBP_POLICY_PORT == type) - ge0 = gbp_endpoint_find_itf (sw_if_index0); - else - ge0 = gbp_endpoint_find_mac (h0->dst_address, - vnet_buffer (b0)->l2.bd_index); - if (NULL != ge0) - key0.gck_dst = ge0->ge_fwd.gef_sclass; - } - - if (SCLASS_INVALID == key0.gck_dst) - { - /* If you cannot determine the destination EP then drop */ - b0->error = node->errors[GBP_CONTRACT_ERROR_DROP_NO_DCLASS]; - goto trace; - } - - key0.gck_src = vnet_buffer2 (b0)->gbp.sclass; - if (SCLASS_INVALID == key0.gck_src) - { - /* - * the src EPG is not set when the packet arrives on an EPG - * uplink interface and we do not need to apply policy - */ - next0 = gbp_policy_l2_feature_next (gpm, b0, type); - goto trace; - } - - key0.gck_scope = - gbp_bridge_domain_get_scope (vnet_buffer (b0)->l2.bd_index); - - action0 = - gbp_contract_apply (vm, gm, &key0, b0, &rule0, &n_allow_intra, - &n_allow_sclass_1, &acl_match, &rule_match, - &err0, GBP_CONTRACT_APPLY_L2); - switch (action0) - { - case GBP_RULE_PERMIT: - next0 = gbp_policy_l2_feature_next (gpm, b0, type); - vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A; - break; - case GBP_RULE_REDIRECT: - next0 = gbp_rule_l2_redirect (rule0, b0); - vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A; - break; - case GBP_RULE_DENY: - next0 = GBP_POLICY_NEXT_DROP; - b0->error = node->errors[err0]; - break; - } - - trace: - gbp_policy_trace (vm, node, b0, &key0, action0, acl_match, - rule_match); - - /* verify speculative enqueue, maybe switch current next frame */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - GBP_CONTRACT_ERROR_ALLOW_INTRA, n_allow_intra); - vlib_node_increment_counter (vm, node->node_index, - GBP_CONTRACT_ERROR_ALLOW_A_BIT, n_allow_a_bit); - vlib_node_increment_counter (vm, node->node_index, - GBP_CONTRACT_ERROR_ALLOW_SCLASS_1, - n_allow_sclass_1); - - return frame->n_vectors; -} - -VLIB_NODE_FN (gbp_policy_port_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_policy_inline (vm, node, frame, GBP_POLICY_PORT)); -} - -VLIB_NODE_FN (gbp_policy_mac_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_policy_inline (vm, node, frame, GBP_POLICY_MAC)); -} - -VLIB_NODE_FN (gbp_policy_lpm_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return (gbp_policy_inline (vm, node, frame, GBP_POLICY_LPM)); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (gbp_policy_port_node) = { - .name = "gbp-policy-port", - .vector_size = sizeof (u32), - .format_trace = format_gbp_policy_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(gbp_contract_error_strings), - .error_strings = gbp_contract_error_strings, - - .n_next_nodes = GBP_POLICY_N_NEXT, - .next_nodes = { - [GBP_POLICY_NEXT_DROP] = "error-drop", - }, -}; - -VLIB_REGISTER_NODE (gbp_policy_mac_node) = { - .name = "gbp-policy-mac", - .vector_size = sizeof (u32), - .format_trace = format_gbp_policy_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(gbp_contract_error_strings), - .error_strings = gbp_contract_error_strings, - - .n_next_nodes = GBP_POLICY_N_NEXT, - .next_nodes = { - [GBP_POLICY_NEXT_DROP] = "error-drop", - }, -}; - -VLIB_REGISTER_NODE (gbp_policy_lpm_node) = { - .name = "gbp-policy-lpm", - .vector_size = sizeof (u32), - .format_trace = format_gbp_policy_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(gbp_contract_error_strings), - .error_strings = gbp_contract_error_strings, - - .n_next_nodes = GBP_POLICY_N_NEXT, - .next_nodes = { - [GBP_POLICY_NEXT_DROP] = "error-drop", - }, -}; - -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_recirc.c b/src/plugins/gbp/gbp_recirc.c deleted file mode 100644 index 8d56f11b4e3..00000000000 --- a/src/plugins/gbp/gbp_recirc.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp_recirc.h> -#include <plugins/gbp/gbp_endpoint_group.h> -#include <plugins/gbp/gbp_endpoint.h> -#include <plugins/gbp/gbp_itf.h> - -#include <vnet/dpo/dvr_dpo.h> -#include <vnet/fib/fib_table.h> - -#include <vlib/unix/plugin.h> - -/** - * Pool of GBP recircs - */ -gbp_recirc_t *gbp_recirc_pool; - -/** - * Recirc configs keyed by sw_if_index - */ -index_t *gbp_recirc_db; - -/** - * logger - */ -vlib_log_class_t gr_logger; - -/** - * L2 Emulation enable/disable symbols - */ -static void (*l2e_enable) (u32 sw_if_index); -static void (*l2e_disable) (u32 sw_if_index); - -#define GBP_RECIRC_DBG(...) \ - vlib_log_debug (gr_logger, __VA_ARGS__); - -u8 * -format_gbp_recirc (u8 * s, va_list * args) -{ - gbp_recirc_t *gr = va_arg (*args, gbp_recirc_t *); - vnet_main_t *vnm = vnet_get_main (); - - return format (s, " %U, sclass:%d, ext:%d", - format_vnet_sw_if_index_name, vnm, - gr->gr_sw_if_index, gr->gr_sclass, gr->gr_is_ext); -} - -int -gbp_recirc_add (u32 sw_if_index, sclass_t sclass, u8 is_ext) -{ - gbp_recirc_t *gr; - index_t gri; - - vec_validate_init_empty (gbp_recirc_db, sw_if_index, INDEX_INVALID); - - gri = gbp_recirc_db[sw_if_index]; - - if (INDEX_INVALID == gri) - { - gbp_endpoint_group_t *gg; - fib_protocol_t fproto; - index_t ggi; - - ggi = gbp_endpoint_group_find (sclass); - - if (INDEX_INVALID == ggi) - return (VNET_API_ERROR_NO_SUCH_ENTRY); - - gbp_endpoint_group_lock (ggi); - pool_get_zero (gbp_recirc_pool, gr); - gri = gr - gbp_recirc_pool; - - gr->gr_sclass = sclass; - gr->gr_is_ext = is_ext; - gr->gr_sw_if_index = sw_if_index; - - /* - * IP enable the recirc interface - */ - ip4_sw_interface_enable_disable (gr->gr_sw_if_index, 1); - ip6_sw_interface_enable_disable (gr->gr_sw_if_index, 1); - - /* - * cache the FIB indicies of the EPG - */ - gr->gr_epgi = ggi; - - gg = gbp_endpoint_group_get (gr->gr_epgi); - FOR_EACH_FIB_IP_PROTOCOL (fproto) - { - gr->gr_fib_index[fib_proto_to_dpo (fproto)] = - gbp_endpoint_group_get_fib_index (gg, fproto); - } - - /* - * bind to the bridge-domain of the EPG - */ - gr->gr_itf = gbp_itf_l2_add_and_lock (gr->gr_sw_if_index, gg->gg_gbd); - - /* - * set the interface into L2 emulation mode - */ - l2e_enable (gr->gr_sw_if_index); - - /* - * Packets on the recirculation interface are subject to src-EPG - * classification. Recirc interfaces are L2-emulation mode. - * for internal EPGs this is via an LPM on all external subnets. - * for external EPGs this is via a port mapping. - */ - if (gr->gr_is_ext) - { - mac_address_t mac; - /* - * recirc is for post-NAT translation packets going into - * the external EPG, these are classified to the NAT EPG - * based on its port - */ - mac_address_from_bytes (&mac, - vnet_sw_interface_get_hw_address - (vnet_get_main (), gr->gr_sw_if_index)); - gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_CP, - gr->gr_sw_if_index, - NULL, &mac, INDEX_INVALID, - INDEX_INVALID, gr->gr_sclass, - GBP_ENDPOINT_FLAG_NONE, - NULL, NULL, &gr->gr_ep); - vnet_feature_enable_disable ("ip4-unicast", - "ip4-gbp-src-classify", - gr->gr_sw_if_index, 1, 0, 0); - vnet_feature_enable_disable ("ip6-unicast", - "ip6-gbp-src-classify", - gr->gr_sw_if_index, 1, 0, 0); - } - else - { - /* - * recirc is for pre-NAT translation packets coming from - * the external EPG, these are classified based on a LPM - * in the EPG's route-domain - */ - vnet_feature_enable_disable ("ip4-unicast", - "ip4-gbp-lpm-classify", - gr->gr_sw_if_index, 1, 0, 0); - vnet_feature_enable_disable ("ip6-unicast", - "ip6-gbp-lpm-classify", - gr->gr_sw_if_index, 1, 0, 0); - } - - gbp_recirc_db[sw_if_index] = gri; - } - else - { - gr = gbp_recirc_get (gri); - } - - GBP_RECIRC_DBG ("add: %U", format_gbp_recirc, gr); - return (0); -} - -int -gbp_recirc_delete (u32 sw_if_index) -{ - gbp_recirc_t *gr; - index_t gri; - - if (vec_len (gbp_recirc_db) <= sw_if_index) - return VNET_API_ERROR_INVALID_SW_IF_INDEX; - gri = gbp_recirc_db[sw_if_index]; - - if (INDEX_INVALID != gri) - { - gr = pool_elt_at_index (gbp_recirc_pool, gri); - - GBP_RECIRC_DBG ("del: %U", format_gbp_recirc, gr); - - if (gr->gr_is_ext) - { - gbp_endpoint_unlock (GBP_ENDPOINT_SRC_CP, gr->gr_ep); - vnet_feature_enable_disable ("ip4-unicast", - "ip4-gbp-src-classify", - gr->gr_sw_if_index, 0, 0, 0); - vnet_feature_enable_disable ("ip6-unicast", - "ip6-gbp-src-classify", - gr->gr_sw_if_index, 0, 0, 0); - } - else - { - vnet_feature_enable_disable ("ip4-unicast", - "ip4-gbp-lpm-classify", - gr->gr_sw_if_index, 0, 0, 0); - vnet_feature_enable_disable ("ip6-unicast", - "ip6-gbp-lpm-classify", - gr->gr_sw_if_index, 0, 0, 0); - } - - ip4_sw_interface_enable_disable (gr->gr_sw_if_index, 0); - ip6_sw_interface_enable_disable (gr->gr_sw_if_index, 0); - l2e_disable (gr->gr_sw_if_index); - - gbp_itf_unlock (&gr->gr_itf); - - gbp_endpoint_group_unlock (gr->gr_epgi); - gbp_recirc_db[sw_if_index] = INDEX_INVALID; - pool_put (gbp_recirc_pool, gr); - return (0); - } - return VNET_API_ERROR_NO_SUCH_ENTRY; -} - -void -gbp_recirc_walk (gbp_recirc_cb_t cb, void *ctx) -{ - gbp_recirc_t *ge; - - /* *INDENT-OFF* */ - pool_foreach (ge, gbp_recirc_pool) - { - if (!cb(ge, ctx)) - break; - } - /* *INDENT-ON* */ -} - -static walk_rc_t -gbp_recirc_show_one (gbp_recirc_t * gr, void *ctx) -{ - vlib_cli_output (ctx, " %U", format_gbp_recirc, gr); - - return (WALK_CONTINUE); -} - -static clib_error_t * -gbp_recirc_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - vlib_cli_output (vm, "Recirculation-Interfaces:"); - gbp_recirc_walk (gbp_recirc_show_one, vm); - - return (NULL); -} - -/*? - * Show Group Based Policy Recircs and derived information - * - * @cliexpar - * @cliexstart{show gbp recirc} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_recirc_show_node, static) = { - .path = "show gbp recirc", - .short_help = "show gbp recirc\n", - .function = gbp_recirc_show, -}; -/* *INDENT-ON* */ - -static clib_error_t * -gbp_recirc_init (vlib_main_t * vm) -{ - gr_logger = vlib_log_register_class ("gbp", "recirc"); - - l2e_enable = - vlib_get_plugin_symbol ("l2e_plugin.so", "l2_emulation_enable"); - l2e_disable = - vlib_get_plugin_symbol ("l2e_plugin.so", "l2_emulation_disable"); - - return (NULL); -} - -VLIB_INIT_FUNCTION (gbp_recirc_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_recirc.h b/src/plugins/gbp/gbp_recirc.h deleted file mode 100644 index 2f3354b794e..00000000000 --- a/src/plugins/gbp/gbp_recirc.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_RECIRC_H__ -#define __GBP_RECIRC_H__ - -#include <plugins/gbp/gbp_types.h> -#include <plugins/gbp/gbp_itf.h> -#include <vnet/fib/fib_types.h> - -/** - * A GBP recirculation interface representation - * Thes interfaces join Bridge domains that are internal to those that are - * NAT external, so the packets can be NAT translated and then undergo the - * whole policy process again. - */ -typedef struct gpb_recirc_t_ -{ - /** - * EPG ID that packets will classify to when they arrive on this recirc - */ - sclass_t gr_sclass; - - /** - * The index of the EPG - */ - index_t gr_epgi; - - /** - * FIB indices the EPG is mapped to - */ - u32 gr_fib_index[DPO_PROTO_NUM]; - - /** - * Is the interface for packets post-NAT translation (i.e. ext) - * or pre-NAT translation (i.e. internal) - */ - u8 gr_is_ext; - - /** - */ - u32 gr_sw_if_index; - gbp_itf_hdl_t gr_itf; - - /** - * The endpoint created to represent the reric interface - */ - index_t gr_ep; -} gbp_recirc_t; - -extern int gbp_recirc_add (u32 sw_if_index, sclass_t sclass, u8 is_ext); -extern int gbp_recirc_delete (u32 sw_if_index); - -typedef walk_rc_t (*gbp_recirc_cb_t) (gbp_recirc_t * gbpe, void *ctx); -extern void gbp_recirc_walk (gbp_recirc_cb_t bgpe, void *ctx); - -/** - * Data plane functions - */ -extern gbp_recirc_t *gbp_recirc_pool; -extern index_t *gbp_recirc_db; - -always_inline gbp_recirc_t * -gbp_recirc_get (u32 sw_if_index) -{ - return (pool_elt_at_index (gbp_recirc_pool, gbp_recirc_db[sw_if_index])); -} -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_route_domain.c b/src/plugins/gbp/gbp_route_domain.c deleted file mode 100644 index 6cc595d0fa9..00000000000 --- a/src/plugins/gbp/gbp_route_domain.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp_route_domain.h> -#include <plugins/gbp/gbp_endpoint.h> - -#include <vnet/dpo/dvr_dpo.h> -#include <vnet/fib/fib_table.h> - -/** - * A fixed MAC address to use as the source MAC for packets L3 switched - * onto the routed uu-fwd interfaces. - * Magic values - origin lost to the mists of time... - */ -/* *INDENT-OFF* */ -const static mac_address_t GBP_ROUTED_SRC_MAC = { - .bytes = { - 0x0, 0x22, 0xBD, 0xF8, 0x19, 0xFF, - } -}; - -const static mac_address_t GBP_ROUTED_DST_MAC = { - .bytes = { - 00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - } -}; -/* *INDENT-ON* */ - -/** - * Pool of GBP route_domains - */ -gbp_route_domain_t *gbp_route_domain_pool; - -/** - * DB of route_domains - */ -typedef struct gbp_route_domain_db_t -{ - uword *gbd_by_rd_id; -} gbp_route_domain_db_t; - -static gbp_route_domain_db_t gbp_route_domain_db; -static fib_source_t gbp_fib_source; - -/** - * logger - */ -vlib_log_class_t grd_logger; - -#define GBP_BD_DBG(...) \ - vlib_log_debug (grd_logger, __VA_ARGS__); - -index_t -gbp_route_domain_index (const gbp_route_domain_t * grd) -{ - return (grd - gbp_route_domain_pool); -} - -gbp_route_domain_t * -gbp_route_domain_get (index_t i) -{ - return (pool_elt_at_index (gbp_route_domain_pool, i)); -} - -static void -gbp_route_domain_lock (index_t i) -{ - gbp_route_domain_t *grd; - - grd = gbp_route_domain_get (i); - grd->grd_locks++; -} - -index_t -gbp_route_domain_find (u32 rd_id) -{ - uword *p; - - p = hash_get (gbp_route_domain_db.gbd_by_rd_id, rd_id); - - if (NULL != p) - return p[0]; - - return (INDEX_INVALID); -} - -index_t -gbp_route_domain_find_and_lock (u32 rd_id) -{ - index_t grdi; - - grdi = gbp_route_domain_find (rd_id); - - if (INDEX_INVALID != grdi) - { - gbp_route_domain_lock (grdi); - } - return (grdi); -} - -static void -gbp_route_domain_db_add (gbp_route_domain_t * grd) -{ - index_t grdi = grd - gbp_route_domain_pool; - - hash_set (gbp_route_domain_db.gbd_by_rd_id, grd->grd_id, grdi); -} - -static void -gbp_route_domain_db_remove (gbp_route_domain_t * grd) -{ - hash_unset (gbp_route_domain_db.gbd_by_rd_id, grd->grd_id); -} - -int -gbp_route_domain_add_and_lock (u32 rd_id, - gbp_scope_t scope, - u32 ip4_table_id, - u32 ip6_table_id, - u32 ip4_uu_sw_if_index, u32 ip6_uu_sw_if_index) -{ - gbp_route_domain_t *grd; - index_t grdi; - - grdi = gbp_route_domain_find (rd_id); - - if (INDEX_INVALID == grdi) - { - fib_protocol_t fproto; - - pool_get_zero (gbp_route_domain_pool, grd); - - grd->grd_id = rd_id; - grd->grd_scope = scope; - grd->grd_table_id[FIB_PROTOCOL_IP4] = ip4_table_id; - grd->grd_table_id[FIB_PROTOCOL_IP6] = ip6_table_id; - grd->grd_uu_sw_if_index[FIB_PROTOCOL_IP4] = ip4_uu_sw_if_index; - grd->grd_uu_sw_if_index[FIB_PROTOCOL_IP6] = ip6_uu_sw_if_index; - - FOR_EACH_FIB_IP_PROTOCOL (fproto) - { - grd->grd_fib_index[fproto] = - fib_table_find_or_create_and_lock (fproto, - grd->grd_table_id[fproto], - gbp_fib_source); - - if (~0 != grd->grd_uu_sw_if_index[fproto]) - { - ethernet_header_t *eth; - u8 *rewrite; - - rewrite = NULL; - vec_validate (rewrite, sizeof (*eth) - 1); - eth = (ethernet_header_t *) rewrite; - - eth->type = clib_host_to_net_u16 ((fproto == FIB_PROTOCOL_IP4 ? - ETHERNET_TYPE_IP4 : - ETHERNET_TYPE_IP6)); - - mac_address_to_bytes (gbp_route_domain_get_local_mac (), - eth->src_address); - mac_address_to_bytes (gbp_route_domain_get_remote_mac (), - eth->dst_address); - - /* - * create an adjacency out of the uu-fwd interfaces that will - * be used when adding subnet routes. - */ - grd->grd_adj[fproto] = - adj_nbr_add_or_lock_w_rewrite (fproto, - fib_proto_to_link (fproto), - &ADJ_BCAST_ADDR, - grd->grd_uu_sw_if_index[fproto], - rewrite); - } - else - { - grd->grd_adj[fproto] = INDEX_INVALID; - } - } - - gbp_route_domain_db_add (grd); - } - else - { - grd = gbp_route_domain_get (grdi); - } - - grd->grd_locks++; - GBP_BD_DBG ("add: %U", format_gbp_route_domain, grd); - - return (0); -} - -void -gbp_route_domain_unlock (index_t index) -{ - gbp_route_domain_t *grd; - - grd = gbp_route_domain_get (index); - - grd->grd_locks--; - - if (0 == grd->grd_locks) - { - fib_protocol_t fproto; - - GBP_BD_DBG ("destroy: %U", format_gbp_route_domain, grd); - - FOR_EACH_FIB_IP_PROTOCOL (fproto) - { - fib_table_unlock (grd->grd_fib_index[fproto], fproto, gbp_fib_source); - if (INDEX_INVALID != grd->grd_adj[fproto]) - adj_unlock (grd->grd_adj[fproto]); - } - - gbp_route_domain_db_remove (grd); - - pool_put (gbp_route_domain_pool, grd); - } -} - -u32 -gbp_route_domain_get_rd_id (index_t grdi) -{ - gbp_route_domain_t *grd; - - grd = gbp_route_domain_get (grdi); - - return (grd->grd_id); -} - -gbp_scope_t -gbp_route_domain_get_scope (index_t grdi) -{ - gbp_route_domain_t *grd; - - grd = gbp_route_domain_get (grdi); - - return (grd->grd_scope); -} - -int -gbp_route_domain_delete (u32 rd_id) -{ - index_t grdi; - - GBP_BD_DBG ("del: %d", rd_id); - grdi = gbp_route_domain_find (rd_id); - - if (INDEX_INVALID != grdi) - { - GBP_BD_DBG ("del: %U", format_gbp_route_domain, - gbp_route_domain_get (grdi)); - gbp_route_domain_unlock (grdi); - - return (0); - } - - return (VNET_API_ERROR_NO_SUCH_ENTRY); -} - -const mac_address_t * -gbp_route_domain_get_local_mac (void) -{ - return (&GBP_ROUTED_SRC_MAC); -} - -const mac_address_t * -gbp_route_domain_get_remote_mac (void) -{ - return (&GBP_ROUTED_DST_MAC); -} - -void -gbp_route_domain_walk (gbp_route_domain_cb_t cb, void *ctx) -{ - gbp_route_domain_t *gbpe; - - /* *INDENT-OFF* */ - pool_foreach (gbpe, gbp_route_domain_pool) - { - if (!cb(gbpe, ctx)) - break; - } - /* *INDENT-ON* */ -} - -static clib_error_t * -gbp_route_domain_cli (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - vnet_main_t *vnm = vnet_get_main (); - u32 ip4_uu_sw_if_index = ~0; - u32 ip6_uu_sw_if_index = ~0; - u32 ip4_table_id = ~0; - u32 ip6_table_id = ~0; - u32 scope = ~0; - u32 rd_id = ~0; - u8 add = 1; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "ip4-uu %U", unformat_vnet_sw_interface, - vnm, &ip4_uu_sw_if_index)) - ; - else if (unformat (input, "ip6-uu %U", unformat_vnet_sw_interface, - vnm, &ip6_uu_sw_if_index)) - ; - else if (unformat (input, "ip4-table-id %d", &ip4_table_id)) - ; - else if (unformat (input, "ip6-table-id %d", &ip6_table_id)) - ; - else if (unformat (input, "add")) - add = 1; - else if (unformat (input, "del")) - add = 0; - else if (unformat (input, "rd %d", &rd_id)) - ; - else if (unformat (input, "scope %d", &scope)) - ; - else - break; - } - - if (~0 == rd_id) - return clib_error_return (0, "RD-ID must be specified"); - - if (add) - { - if (~0 == ip4_table_id) - return clib_error_return (0, "IP4 table-ID must be specified"); - if (~0 == ip6_table_id) - return clib_error_return (0, "IP6 table-ID must be specified"); - - gbp_route_domain_add_and_lock (rd_id, scope, - ip4_table_id, - ip6_table_id, - ip4_uu_sw_if_index, ip6_uu_sw_if_index); - } - else - gbp_route_domain_delete (rd_id); - - return (NULL); -} - -/*? - * Configure a GBP route-domain - * - * @cliexpar - * @cliexstart{gbp route-domain [del] rd <ID> ip4-table-id <ID> ip6-table-id <ID> [ip4-uu <interface>] [ip6-uu <interface>]} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_route_domain_cli_node, static) = { - .path = "gbp route-domain", - .short_help = "gbp route-domain [del] rd <ID> ip4-table-id <ID> ip6-table-id <ID> [ip4-uu <interface>] [ip6-uu <interface>]", - .function = gbp_route_domain_cli, -}; - -u8 * -format_gbp_route_domain (u8 * s, va_list * args) -{ - gbp_route_domain_t *grd = va_arg (*args, gbp_route_domain_t*); - vnet_main_t *vnm = vnet_get_main (); - - if (NULL != grd) - s = format (s, "[%d] rd:%d ip4-uu:%U ip6-uu:%U locks:%d", - grd - gbp_route_domain_pool, - grd->grd_id, - format_vnet_sw_if_index_name, vnm, grd->grd_uu_sw_if_index[FIB_PROTOCOL_IP4], - format_vnet_sw_if_index_name, vnm, grd->grd_uu_sw_if_index[FIB_PROTOCOL_IP6], - grd->grd_locks); - else - s = format (s, "NULL"); - - return (s); -} - -static int -gbp_route_domain_show_one (gbp_route_domain_t *gb, void *ctx) -{ - vlib_main_t *vm; - - vm = ctx; - vlib_cli_output (vm, " %U",format_gbp_route_domain, gb); - - return (1); -} - -static clib_error_t * -gbp_route_domain_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - vlib_cli_output (vm, "Route-Domains:"); - gbp_route_domain_walk (gbp_route_domain_show_one, vm); - - return (NULL); -} - -/*? - * Show Group Based Policy Route_Domains and derived information - * - * @cliexpar - * @cliexstart{show gbp route_domain} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_route_domain_show_node, static) = { - .path = "show gbp route-domain", - .short_help = "show gbp route-domain\n", - .function = gbp_route_domain_show, -}; -/* *INDENT-ON* */ - -static clib_error_t * -gbp_route_domain_init (vlib_main_t * vm) -{ - grd_logger = vlib_log_register_class ("gbp", "rd"); - gbp_fib_source = fib_source_allocate ("gbp-rd", - FIB_SOURCE_PRIORITY_HI, - FIB_SOURCE_BH_DROP); - - return (NULL); -} - -VLIB_INIT_FUNCTION (gbp_route_domain_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_route_domain.h b/src/plugins/gbp/gbp_route_domain.h deleted file mode 100644 index 897c1bdd7ac..00000000000 --- a/src/plugins/gbp/gbp_route_domain.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_ROUTE_DOMAIN_H__ -#define __GBP_ROUTE_DOMAIN_H__ - -#include <plugins/gbp/gbp_types.h> - -#include <vnet/fib/fib_types.h> -#include <vnet/ethernet/mac_address.h> - -/** - * A route Domain Representation. - * This is a standard route-domain plus all the attributes it must - * have to supprt the GBP model. - */ -typedef struct gpb_route_domain_t_ -{ - /** - * Route-domain ID - */ - u32 grd_id; - gbp_scope_t grd_scope; - u32 grd_fib_index[FIB_PROTOCOL_IP_MAX]; - u32 grd_table_id[FIB_PROTOCOL_IP_MAX]; - - /** - * The interfaces on which to send packets to unnknown EPs - */ - u32 grd_uu_sw_if_index[FIB_PROTOCOL_IP_MAX]; - - /** - * adjacencies on the UU interfaces. - */ - u32 grd_adj[FIB_PROTOCOL_IP_MAX]; - - u32 grd_locks; -} gbp_route_domain_t; - -extern int gbp_route_domain_add_and_lock (u32 rd_id, - gbp_scope_t scope, - u32 ip4_table_id, - u32 ip6_table_id, - u32 ip4_uu_sw_if_index, - u32 ip6_uu_sw_if_index); -extern void gbp_route_domain_unlock (index_t grdi); -extern index_t gbp_route_domain_find_and_lock (u32 rd_id); -extern index_t gbp_route_domain_find (u32 rd_id); -extern index_t gbp_route_domain_index (const gbp_route_domain_t *); - -extern int gbp_route_domain_delete (u32 rd_id); -extern gbp_route_domain_t *gbp_route_domain_get (index_t i); -extern u32 gbp_route_domain_get_rd_id (index_t i); -extern gbp_scope_t gbp_route_domain_get_scope (index_t i); - -typedef int (*gbp_route_domain_cb_t) (gbp_route_domain_t * gb, void *ctx); -extern void gbp_route_domain_walk (gbp_route_domain_cb_t bgpe, void *ctx); - -extern const mac_address_t *gbp_route_domain_get_local_mac (void); -extern const mac_address_t *gbp_route_domain_get_remote_mac (void); - -extern u8 *format_gbp_route_domain (u8 * s, va_list * args); - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_scanner.c b/src/plugins/gbp/gbp_scanner.c deleted file mode 100644 index 9ae962b7449..00000000000 --- a/src/plugins/gbp/gbp_scanner.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * gbp.h : Group Based Policy - * - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp_scanner.h> -#include <plugins/gbp/gbp_endpoint.h> -#include <plugins/gbp/gbp_vxlan.h> - -/** - * Scanner logger - */ -vlib_log_class_t gs_logger; - -/** - * Scanner state - */ -static bool gs_enabled; - -#define GBP_SCANNER_DBG(...) \ - vlib_log_debug (gs_logger, __VA_ARGS__); - -static uword -gbp_scanner (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) -{ - uword event_type, *event_data = 0; - bool do_scan = 0; - - while (1) - { - do_scan = 0; - - if (gs_enabled) - { - /* scan every 'inactive threshold' seconds */ - vlib_process_wait_for_event_or_clock (vm, 2); - } - else - vlib_process_wait_for_event (vm); - - event_type = vlib_process_get_events (vm, &event_data); - vec_reset_length (event_data); - - switch (event_type) - { - case ~0: - /* timer expired */ - do_scan = 1; - break; - - case GBP_ENDPOINT_SCAN_START: - gs_enabled = 1; - break; - - case GBP_ENDPOINT_SCAN_STOP: - gs_enabled = 0; - break; - - case GBP_ENDPOINT_SCAN_SET_TIME: - break; - - default: - ASSERT (0); - } - - if (do_scan) - { - GBP_SCANNER_DBG ("start"); - gbp_endpoint_scan (vm); - GBP_SCANNER_DBG ("stop"); - } - } - return 0; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (gbp_scanner_node) = { - .function = gbp_scanner, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "gbp-scanner", -}; -/* *INDENT-ON* */ - -static clib_error_t * -gbp_scanner_cli (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - vlib_cli_output (vm, "GBP-scanner: enabled:%d interval:2", gs_enabled); - - return (NULL); -} - -/*? - * Show GBP scanner - * - * @cliexpar - * @cliexstart{show gbp scanner} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_scanner_cli_node, static) = { - .path = "show gbp scanner", - .short_help = "show gbp scanner", - .function = gbp_scanner_cli, -}; -/* *INDENT-ON* */ - -static clib_error_t * -gbp_scanner_init (vlib_main_t * vm) -{ - gs_logger = vlib_log_register_class ("gbp", "scan"); - - return (NULL); -} - -VLIB_INIT_FUNCTION (gbp_scanner_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_scanner.h b/src/plugins/gbp/gbp_scanner.h deleted file mode 100644 index 1133167d927..00000000000 --- a/src/plugins/gbp/gbp_scanner.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_SCANNER_H__ -#define __GBP_SCANNER_H__ - -#include <vlib/vlib.h> - -typedef enum gbp_scan_event_t_ -{ - GBP_ENDPOINT_SCAN_START, - GBP_ENDPOINT_SCAN_STOP, - GBP_ENDPOINT_SCAN_SET_TIME, -} gbp_scan_event_t; - -extern vlib_node_registration_t gbp_scanner_node; - -#endif diff --git a/src/plugins/gbp/gbp_subnet.c b/src/plugins/gbp/gbp_subnet.c deleted file mode 100644 index 8d3b571657c..00000000000 --- a/src/plugins/gbp/gbp_subnet.c +++ /dev/null @@ -1,598 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp.h> -#include <plugins/gbp/gbp_fwd_dpo.h> -#include <plugins/gbp/gbp_policy_dpo.h> -#include <plugins/gbp/gbp_route_domain.h> - -#include <vnet/fib/fib_table.h> -#include <vnet/dpo/load_balance.h> - -/** - * a key for the DB - */ -typedef struct gbp_subnet_key_t_ -{ - fib_prefix_t gsk_pfx; - u32 gsk_fib_index; -} gbp_subnet_key_t; - -/** - * Subnet - */ -typedef struct gbp_subnet_t_ -{ - gbp_subnet_key_t *gs_key; - gbp_subnet_type_t gs_type; - index_t gs_rd; - - union - { - struct - { - sclass_t gs_sclass; - u32 gs_sw_if_index; - } gs_stitched_external; - struct - { - sclass_t gs_sclass; - } gs_l3_out; - }; - - fib_node_index_t gs_fei; -} gbp_subnet_t; - -/** - * A DB of the subnets; key={pfx,fib-index} - */ -uword *gbp_subnet_db; - -/** - * pool of subnets - */ -gbp_subnet_t *gbp_subnet_pool; - -static fib_source_t gbp_fib_source; - -static index_t -gbp_subnet_db_find (u32 fib_index, const fib_prefix_t * pfx) -{ - gbp_subnet_key_t key = { - .gsk_pfx = *pfx, - .gsk_fib_index = fib_index, - }; - uword *p; - - p = hash_get_mem (gbp_subnet_db, &key); - - if (NULL != p) - return p[0]; - - return (INDEX_INVALID); -} - -static void -gbp_subnet_db_add (u32 fib_index, const fib_prefix_t * pfx, gbp_subnet_t * gs) -{ - gbp_subnet_key_t *key; - - key = clib_mem_alloc (sizeof (*key)); - - clib_memcpy (&(key->gsk_pfx), pfx, sizeof (*pfx)); - key->gsk_fib_index = fib_index; - - hash_set_mem (gbp_subnet_db, key, (gs - gbp_subnet_pool)); - - gs->gs_key = key; -} - -static void -gbp_subnet_db_del (gbp_subnet_t * gs) -{ - hash_unset_mem (gbp_subnet_db, gs->gs_key); - - clib_mem_free (gs->gs_key); - gs->gs_key = NULL; -} - - -static int -gbp_subnet_transport_add (gbp_subnet_t * gs) -{ - dpo_id_t gfd = DPO_INVALID; - gbp_route_domain_t *grd; - fib_protocol_t fproto; - - fproto = gs->gs_key->gsk_pfx.fp_proto; - grd = gbp_route_domain_get (gs->gs_rd); - - if (~0 == grd->grd_uu_sw_if_index[fproto]) - return (VNET_API_ERROR_INVALID_SW_IF_INDEX); - - gs->gs_fei = fib_table_entry_update_one_path (gs->gs_key->gsk_fib_index, - &gs->gs_key->gsk_pfx, - gbp_fib_source, - FIB_ENTRY_FLAG_NONE, - fib_proto_to_dpo (fproto), - &ADJ_BCAST_ADDR, - grd->grd_uu_sw_if_index - [fproto], ~0, 1, NULL, - FIB_ROUTE_PATH_FLAG_NONE); - - dpo_reset (&gfd); - - return (0); -} - -static int -gbp_subnet_internal_add (gbp_subnet_t * gs) -{ - dpo_id_t gfd = DPO_INVALID; - - gbp_fwd_dpo_add_or_lock (fib_proto_to_dpo (gs->gs_key->gsk_pfx.fp_proto), - &gfd); - - gs->gs_fei = fib_table_entry_special_dpo_update (gs->gs_key->gsk_fib_index, - &gs->gs_key->gsk_pfx, - gbp_fib_source, - FIB_ENTRY_FLAG_EXCLUSIVE, - &gfd); - - dpo_reset (&gfd); - - return (0); -} - -static int -gbp_subnet_external_add (gbp_subnet_t * gs, u32 sw_if_index, sclass_t sclass) -{ - dpo_id_t gpd = DPO_INVALID; - - gs->gs_stitched_external.gs_sclass = sclass; - gs->gs_stitched_external.gs_sw_if_index = sw_if_index; - - gbp_policy_dpo_add_or_lock (fib_proto_to_dpo (gs->gs_key->gsk_pfx.fp_proto), - gbp_route_domain_get_scope (gs->gs_rd), - gs->gs_stitched_external.gs_sclass, - gs->gs_stitched_external.gs_sw_if_index, &gpd); - - gs->gs_fei = fib_table_entry_special_dpo_update (gs->gs_key->gsk_fib_index, - &gs->gs_key->gsk_pfx, - gbp_fib_source, - (FIB_ENTRY_FLAG_EXCLUSIVE | - FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT), - &gpd); - - dpo_reset (&gpd); - - return (0); -} - -static int -gbp_subnet_l3_out_add (gbp_subnet_t * gs, sclass_t sclass, int is_anon) -{ - fib_entry_flag_t flags; - dpo_id_t gpd = DPO_INVALID; - - gs->gs_l3_out.gs_sclass = sclass; - - gbp_policy_dpo_add_or_lock (fib_proto_to_dpo (gs->gs_key->gsk_pfx.fp_proto), - gbp_route_domain_get_scope (gs->gs_rd), - gs->gs_l3_out.gs_sclass, ~0, &gpd); - - flags = FIB_ENTRY_FLAG_INTERPOSE; - if (is_anon) - flags |= FIB_ENTRY_FLAG_COVERED_INHERIT; - - gs->gs_fei = fib_table_entry_special_dpo_add (gs->gs_key->gsk_fib_index, - &gs->gs_key->gsk_pfx, - FIB_SOURCE_SPECIAL, - flags, &gpd); - - dpo_reset (&gpd); - - return (0); -} - -static void -gbp_subnet_del_i (index_t gsi) -{ - gbp_subnet_t *gs; - - gs = pool_elt_at_index (gbp_subnet_pool, gsi); - - fib_table_entry_delete_index (gs->gs_fei, - (GBP_SUBNET_L3_OUT == gs->gs_type - || GBP_SUBNET_ANON_L3_OUT == - gs->gs_type) ? FIB_SOURCE_SPECIAL : - gbp_fib_source); - - gbp_subnet_db_del (gs); - gbp_route_domain_unlock (gs->gs_rd); - - pool_put (gbp_subnet_pool, gs); -} - -int -gbp_subnet_del (u32 rd_id, const fib_prefix_t * pfx) -{ - gbp_route_domain_t *grd; - index_t gsi, grdi; - u32 fib_index; - - grdi = gbp_route_domain_find (rd_id); - - if (~0 == grdi) - return (VNET_API_ERROR_NO_SUCH_FIB); - - grd = gbp_route_domain_get (grdi); - fib_index = grd->grd_fib_index[pfx->fp_proto]; - - gsi = gbp_subnet_db_find (fib_index, pfx); - - if (INDEX_INVALID == gsi) - return (VNET_API_ERROR_NO_SUCH_ENTRY); - - gbp_subnet_del_i (gsi); - - return (0); -} - -int -gbp_subnet_add (u32 rd_id, - const fib_prefix_t * pfx, - gbp_subnet_type_t type, u32 sw_if_index, sclass_t sclass) -{ - gbp_route_domain_t *grd; - index_t grdi, gsi; - gbp_subnet_t *gs; - u32 fib_index; - int rv; - - switch (type) - { - case GBP_SUBNET_TRANSPORT: - case GBP_SUBNET_STITCHED_INTERNAL: - case GBP_SUBNET_STITCHED_EXTERNAL: - case GBP_SUBNET_L3_OUT: - case GBP_SUBNET_ANON_L3_OUT: - break; - default: - return (VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE); - } - - grdi = gbp_route_domain_find_and_lock (rd_id); - - if (~0 == grdi) - return (VNET_API_ERROR_NO_SUCH_FIB); - - grd = gbp_route_domain_get (grdi); - fib_index = grd->grd_fib_index[pfx->fp_proto]; - - gsi = gbp_subnet_db_find (fib_index, pfx); - - /* - * this is an update if the subnet already exists, so remove the old - */ - if (INDEX_INVALID != gsi) - gbp_subnet_del_i (gsi); - - rv = -2; - - pool_get (gbp_subnet_pool, gs); - - gs->gs_type = type; - gs->gs_rd = grdi; - gbp_subnet_db_add (fib_index, pfx, gs); - - switch (type) - { - case GBP_SUBNET_STITCHED_INTERNAL: - rv = gbp_subnet_internal_add (gs); - break; - case GBP_SUBNET_STITCHED_EXTERNAL: - rv = gbp_subnet_external_add (gs, sw_if_index, sclass); - break; - case GBP_SUBNET_TRANSPORT: - rv = gbp_subnet_transport_add (gs); - break; - case GBP_SUBNET_L3_OUT: - rv = gbp_subnet_l3_out_add (gs, sclass, 0 /* is_anon */ ); - break; - case GBP_SUBNET_ANON_L3_OUT: - rv = gbp_subnet_l3_out_add (gs, sclass, 1 /* is_anon */ ); - break; - } - - return (rv); -} - -static clib_error_t * -gbp_subnet_add_del_cli (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - vnet_main_t *vnm = vnet_get_main (); - fib_prefix_t pfx = {.fp_addr = ip46_address_initializer }; - int length; - u32 rd_id = ~0; - u32 sw_if_index = ~0; - gbp_subnet_type_t type = ~0; - u32 sclass = ~0; - int is_add = 1; - int rv; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "rd %d", &rd_id)) - ; - else - if (unformat - (line_input, "prefix %U/%d", unformat_ip4_address, - &pfx.fp_addr.ip4, &length)) - pfx.fp_proto = FIB_PROTOCOL_IP4; - else - if (unformat - (line_input, "prefix %U/%d", unformat_ip6_address, - &pfx.fp_addr.ip6, &length)) - pfx.fp_proto = FIB_PROTOCOL_IP6; - else if (unformat (line_input, "type transport")) - type = GBP_SUBNET_TRANSPORT; - else if (unformat (line_input, "type stitched-internal")) - type = GBP_SUBNET_STITCHED_INTERNAL; - else if (unformat (line_input, "type stitched-external")) - type = GBP_SUBNET_STITCHED_EXTERNAL; - else if (unformat (line_input, "type anon-l3-out")) - type = GBP_SUBNET_ANON_L3_OUT; - else if (unformat (line_input, "type l3-out")) - type = GBP_SUBNET_L3_OUT; - else - if (unformat_user - (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index)) - ; - else if (unformat (line_input, "sclass %u", &sclass)) - ; - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, line_input); - } - unformat_free (line_input); - - pfx.fp_len = length; - - if (is_add) - rv = gbp_subnet_add (rd_id, &pfx, type, sw_if_index, sclass); - else - rv = gbp_subnet_del (rd_id, &pfx); - - switch (rv) - { - case 0: - return 0; - case VNET_API_ERROR_NO_SUCH_FIB: - return clib_error_return (0, "no such FIB"); - } - - return clib_error_return (0, "unknown error %d", rv); -} - -/*? - * Add Group Based Policy Subnets - * - * @cliexpar - * @cliexstart{gbp subnet [del] rd <ID> prefix <prefix> type <type> [<interface>] [sclass <sclass>]} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_subnet_add_del, static) = { - .path = "gbp subnet", - .short_help = "gbp subnet [del] rd <ID> prefix <prefix> type <type> [<interface>] [sclass <sclass>]\n", - .function = gbp_subnet_add_del_cli, -}; -/* *INDENT-ON* */ - - - -void -gbp_subnet_walk (gbp_subnet_cb_t cb, void *ctx) -{ - gbp_route_domain_t *grd; - gbp_subnet_t *gs; - u32 sw_if_index; - sclass_t sclass; - - sclass = SCLASS_INVALID; - sw_if_index = ~0; - - /* *INDENT-OFF* */ - pool_foreach (gs, gbp_subnet_pool) - { - grd = gbp_route_domain_get(gs->gs_rd); - - switch (gs->gs_type) - { - case GBP_SUBNET_STITCHED_INTERNAL: - case GBP_SUBNET_TRANSPORT: - /* use defaults above */ - break; - case GBP_SUBNET_STITCHED_EXTERNAL: - sw_if_index = gs->gs_stitched_external.gs_sw_if_index; - sclass = gs->gs_stitched_external.gs_sclass; - break; - case GBP_SUBNET_L3_OUT: - case GBP_SUBNET_ANON_L3_OUT: - sclass = gs->gs_l3_out.gs_sclass; - break; - } - - if (WALK_STOP == cb (grd->grd_id, &gs->gs_key->gsk_pfx, - gs->gs_type, sw_if_index, sclass, ctx)) - break; - } - /* *INDENT-ON* */ -} - -typedef enum gsb_subnet_show_flags_t_ -{ - GBP_SUBNET_SHOW_BRIEF, - GBP_SUBNET_SHOW_DETAILS, -} gsb_subnet_show_flags_t; - -static u8 * -format_gbp_subnet_type (u8 * s, va_list * args) -{ - gbp_subnet_type_t type = va_arg (*args, gbp_subnet_type_t); - - switch (type) - { - case GBP_SUBNET_STITCHED_INTERNAL: - return (format (s, "stitched-internal")); - case GBP_SUBNET_STITCHED_EXTERNAL: - return (format (s, "stitched-external")); - case GBP_SUBNET_TRANSPORT: - return (format (s, "transport")); - case GBP_SUBNET_L3_OUT: - return (format (s, "l3-out")); - case GBP_SUBNET_ANON_L3_OUT: - return (format (s, "anon-l3-out")); - } - - return (format (s, "unknown")); -} - -u8 * -format_gbp_subnet (u8 * s, va_list * args) -{ - index_t gsi = va_arg (*args, index_t); - gsb_subnet_show_flags_t flags = va_arg (*args, gsb_subnet_show_flags_t); - gbp_subnet_t *gs; - u32 table_id; - - gs = pool_elt_at_index (gbp_subnet_pool, gsi); - - table_id = fib_table_get_table_id (gs->gs_key->gsk_fib_index, - gs->gs_key->gsk_pfx.fp_proto); - - s = format (s, "[%d] tbl:%d %U %U", gsi, table_id, - format_fib_prefix, &gs->gs_key->gsk_pfx, - format_gbp_subnet_type, gs->gs_type); - - switch (gs->gs_type) - { - case GBP_SUBNET_STITCHED_INTERNAL: - case GBP_SUBNET_TRANSPORT: - break; - case GBP_SUBNET_STITCHED_EXTERNAL: - s = format (s, " {sclass:%d %U}", gs->gs_stitched_external.gs_sclass, - format_vnet_sw_if_index_name, - vnet_get_main (), gs->gs_stitched_external.gs_sw_if_index); - break; - case GBP_SUBNET_L3_OUT: - case GBP_SUBNET_ANON_L3_OUT: - s = format (s, " {sclass:%d}", gs->gs_l3_out.gs_sclass); - break; - } - - switch (flags) - { - case GBP_SUBNET_SHOW_DETAILS: - { - s = format (s, "\n %U", format_fib_entry, gs->gs_fei, - FIB_ENTRY_FORMAT_DETAIL); - } - case GBP_SUBNET_SHOW_BRIEF: - break; - } - return (s); -} - -static clib_error_t * -gbp_subnet_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - u32 gsi; - - gsi = INDEX_INVALID; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "%d", &gsi)) - ; - else - break; - } - - if (INDEX_INVALID != gsi) - { - vlib_cli_output (vm, "%U", format_gbp_subnet, gsi, - GBP_SUBNET_SHOW_DETAILS); - } - else - { - /* *INDENT-OFF* */ - pool_foreach_index (gsi, gbp_subnet_pool) - { - vlib_cli_output (vm, "%U", format_gbp_subnet, gsi, - GBP_SUBNET_SHOW_BRIEF); - } - /* *INDENT-ON* */ - } - - return (NULL); -} - -/*? - * Show Group Based Policy Subnets - * - * @cliexpar - * @cliexstart{show gbp subnet} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_subnet_show_node, static) = { - .path = "show gbp subnet", - .short_help = "show gbp subnet\n", - .function = gbp_subnet_show, -}; -/* *INDENT-ON* */ - -static clib_error_t * -gbp_subnet_init (vlib_main_t * vm) -{ - gbp_subnet_db = hash_create_mem (0, - sizeof (gbp_subnet_key_t), sizeof (u32)); - gbp_fib_source = fib_source_allocate ("gbp-subnet", - FIB_SOURCE_PRIORITY_HI, - FIB_SOURCE_BH_SIMPLE); - - return (NULL); -} - -VLIB_INIT_FUNCTION (gbp_subnet_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_subnet.h b/src/plugins/gbp/gbp_subnet.h deleted file mode 100644 index 6fbef01ceba..00000000000 --- a/src/plugins/gbp/gbp_subnet.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_SUBNET_H__ -#define __GBP_SUBNET_H__ - -#include <plugins/gbp/gbp_types.h> - -typedef enum gbp_subnet_type_t_ -{ - GBP_SUBNET_TRANSPORT, - GBP_SUBNET_STITCHED_INTERNAL, - GBP_SUBNET_STITCHED_EXTERNAL, - GBP_SUBNET_L3_OUT, - GBP_SUBNET_ANON_L3_OUT, -} gbp_subnet_type_t; - -extern int gbp_subnet_add (u32 rd_id, - const fib_prefix_t * pfx, - gbp_subnet_type_t type, - u32 sw_if_index, sclass_t sclass); - -extern int gbp_subnet_del (u32 rd_id, const fib_prefix_t * pfx); - -typedef walk_rc_t (*gbp_subnet_cb_t) (u32 rd_id, - const fib_prefix_t * pfx, - gbp_subnet_type_t type, - u32 sw_if_index, - sclass_t sclass, void *ctx); - -extern void gbp_subnet_walk (gbp_subnet_cb_t cb, void *ctx); - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_types.h b/src/plugins/gbp/gbp_types.h deleted file mode 100644 index ac983b1cdd2..00000000000 --- a/src/plugins/gbp/gbp_types.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_TYPES_H__ -#define __GBP_TYPES_H__ - -#include <vnet/vnet.h> - -typedef u32 vnid_t; -#define VNID_INVALID ((u16)~0) - -typedef u16 gbp_scope_t; -typedef u16 sclass_t; -#define SCLASS_INVALID ((u16)~0) - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_vxlan.c b/src/plugins/gbp/gbp_vxlan.c deleted file mode 100644 index 77e4d7ac11b..00000000000 --- a/src/plugins/gbp/gbp_vxlan.c +++ /dev/null @@ -1,654 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include <plugins/gbp/gbp_vxlan.h> -#include <plugins/gbp/gbp_learn.h> -#include <plugins/gbp/gbp_bridge_domain.h> -#include <plugins/gbp/gbp_route_domain.h> - -#include <vnet/vxlan-gbp/vxlan_gbp.h> -#include <vlibmemory/api.h> -#include <vnet/fib/fib_table.h> -#include <vlib/punt.h> - -/** - * A reference to a VXLAN-GBP tunnel created as a child/dependent tunnel - * of the template GBP-VXLAN tunnel - */ -typedef struct vxlan_tunnel_ref_t_ -{ - gbp_itf_hdl_t vxr_itf; - u32 vxr_sw_if_index; - index_t vxr_parent; - gbp_vxlan_tunnel_layer_t vxr_layer; -} vxlan_tunnel_ref_t; - -/** - * DB of added tunnels - */ -uword *gv_db; - -/** - * Logger - */ -static vlib_log_class_t gt_logger; - -/** - * Pool of template tunnels - */ -static gbp_vxlan_tunnel_t *gbp_vxlan_tunnel_pool; - -/** - * Pool of child tunnels - */ -static vxlan_tunnel_ref_t *vxlan_tunnel_ref_pool; - -/** - * DB of template interfaces by SW interface index - */ -static index_t *gbp_vxlan_tunnel_db; - -/** - * DB of child interfaces by SW interface index - */ -static index_t *vxlan_tunnel_ref_db; - -/** - * handle registered with the ;unt infra - */ -static vlib_punt_hdl_t punt_hdl; - -static char *gbp_vxlan_tunnel_layer_strings[] = { -#define _(n,s) [GBP_VXLAN_TUN_##n] = s, - foreach_gbp_vxlan_tunnel_layer -#undef _ -}; - -#define GBP_VXLAN_TUN_DBG(...) \ - vlib_log_debug (gt_logger, __VA_ARGS__); - - -gbp_vxlan_tunnel_t * -gbp_vxlan_tunnel_get (index_t gti) -{ - return (pool_elt_at_index (gbp_vxlan_tunnel_pool, gti)); -} - -static vxlan_tunnel_ref_t * -vxlan_tunnel_ref_get (index_t vxri) -{ - return (pool_elt_at_index (vxlan_tunnel_ref_pool, vxri)); -} - -static u8 * -format_vxlan_tunnel_ref (u8 * s, va_list * args) -{ - index_t vxri = va_arg (*args, u32); - vxlan_tunnel_ref_t *vxr; - - vxr = vxlan_tunnel_ref_get (vxri); - - s = format (s, "[%U]", format_gbp_itf_hdl, vxr->vxr_itf); - - return (s); -} - -static void -gdb_vxlan_dep_del (u32 sw_if_index) -{ - vxlan_tunnel_ref_t *vxr; - gbp_vxlan_tunnel_t *gt; - index_t vxri; - u32 pos; - - vxr = vxlan_tunnel_ref_get (vxlan_tunnel_ref_db[sw_if_index]); - vxri = vxr - vxlan_tunnel_ref_pool; - gt = gbp_vxlan_tunnel_get (vxr->vxr_parent); - - GBP_VXLAN_TUN_DBG ("del-dep:%U", format_vxlan_tunnel_ref, vxri); - - vxlan_tunnel_ref_db[vxr->vxr_sw_if_index] = INDEX_INVALID; - pos = vec_search (gt->gt_tuns, vxri); - - ASSERT (~0 != pos); - vec_del1 (gt->gt_tuns, pos); - - vnet_vxlan_gbp_tunnel_del (vxr->vxr_sw_if_index); - - pool_put (vxlan_tunnel_ref_pool, vxr); -} - -static gbp_itf_hdl_t -gdb_vxlan_dep_add (gbp_vxlan_tunnel_t * gt, - const ip46_address_t * src, const ip46_address_t * dst) -{ - vnet_vxlan_gbp_tunnel_add_del_args_t args = { - .is_add = 1, - .is_ip6 = !ip46_address_is_ip4 (src), - .vni = gt->gt_vni, - .src = *src, - .dst = *dst, - .instance = ~0, - .mode = (GBP_VXLAN_TUN_L2 == gt->gt_layer ? - VXLAN_GBP_TUNNEL_MODE_L2 : VXLAN_GBP_TUNNEL_MODE_L3), - }; - vxlan_tunnel_ref_t *vxr; - u32 sw_if_index; - index_t vxri; - int rv; - - sw_if_index = ~0; - rv = vnet_vxlan_gbp_tunnel_add_del (&args, &sw_if_index); - - if (VNET_API_ERROR_TUNNEL_EXIST == rv) - { - vxri = vxlan_tunnel_ref_db[sw_if_index]; - - vxr = vxlan_tunnel_ref_get (vxri); - gbp_itf_lock (vxr->vxr_itf); - } - else if (0 == rv) - { - ASSERT (~0 != sw_if_index); - GBP_VXLAN_TUN_DBG ("add-dep:%U %U %U %d", format_vnet_sw_if_index_name, - vnet_get_main (), sw_if_index, - format_ip46_address, src, IP46_TYPE_ANY, - format_ip46_address, dst, IP46_TYPE_ANY, gt->gt_vni); - - pool_get_zero (vxlan_tunnel_ref_pool, vxr); - - vxri = (vxr - vxlan_tunnel_ref_pool); - vxr->vxr_parent = gt - gbp_vxlan_tunnel_pool; - vxr->vxr_sw_if_index = sw_if_index; - vxr->vxr_layer = gt->gt_layer; - - /* - * store the child both on the parent's list and the global DB - */ - vec_add1 (gt->gt_tuns, vxri); - - vec_validate_init_empty (vxlan_tunnel_ref_db, - vxr->vxr_sw_if_index, INDEX_INVALID); - vxlan_tunnel_ref_db[vxr->vxr_sw_if_index] = vxri; - - if (GBP_VXLAN_TUN_L2 == vxr->vxr_layer) - { - l2output_feat_masks_t ofeat; - l2input_feat_masks_t ifeat; - gbp_bridge_domain_t *gbd; - - gbd = gbp_bridge_domain_get (gt->gt_gbd); - vxr->vxr_itf = gbp_itf_l2_add_and_lock_w_free - (vxr->vxr_sw_if_index, gt->gt_gbd, gdb_vxlan_dep_del); - - ofeat = L2OUTPUT_FEAT_GBP_POLICY_MAC; - ifeat = L2INPUT_FEAT_NONE; - - if (!(gbd->gb_flags & GBP_BD_FLAG_DO_NOT_LEARN)) - ifeat |= L2INPUT_FEAT_GBP_LEARN; - - gbp_itf_l2_set_output_feature (vxr->vxr_itf, ofeat); - gbp_itf_l2_set_input_feature (vxr->vxr_itf, ifeat); - } - else - { - vxr->vxr_itf = gbp_itf_l3_add_and_lock_w_free - (vxr->vxr_sw_if_index, gt->gt_grd, gdb_vxlan_dep_del); - - gbp_itf_l3_set_input_feature (vxr->vxr_itf, GBP_ITF_L3_FEAT_LEARN); - } - } - else - { - return (GBP_ITF_HDL_INVALID); - } - - return (vxr->vxr_itf); -} - -u32 -vxlan_gbp_tunnel_get_parent (u32 sw_if_index) -{ - ASSERT ((sw_if_index < vec_len (vxlan_tunnel_ref_db)) && - (INDEX_INVALID != vxlan_tunnel_ref_db[sw_if_index])); - - gbp_vxlan_tunnel_t *gt; - vxlan_tunnel_ref_t *vxr; - - vxr = vxlan_tunnel_ref_get (vxlan_tunnel_ref_db[sw_if_index]); - gt = gbp_vxlan_tunnel_get (vxr->vxr_parent); - - return (gt->gt_sw_if_index); -} - -gbp_itf_hdl_t -vxlan_gbp_tunnel_lock_itf (u32 sw_if_index) -{ - ASSERT ((sw_if_index < vec_len (vxlan_tunnel_ref_db)) && - (INDEX_INVALID != vxlan_tunnel_ref_db[sw_if_index])); - - vxlan_tunnel_ref_t *vxr; - - vxr = vxlan_tunnel_ref_get (vxlan_tunnel_ref_db[sw_if_index]); - - gbp_itf_lock (vxr->vxr_itf); - - return (vxr->vxr_itf); -} - - -gbp_vxlan_tunnel_type_t -gbp_vxlan_tunnel_get_type (u32 sw_if_index) -{ - if (sw_if_index < vec_len (vxlan_tunnel_ref_db) && - INDEX_INVALID != vxlan_tunnel_ref_db[sw_if_index]) - { - return (VXLAN_GBP_TUNNEL); - } - else if (sw_if_index < vec_len (gbp_vxlan_tunnel_db) && - INDEX_INVALID != gbp_vxlan_tunnel_db[sw_if_index]) - { - return (GBP_VXLAN_TEMPLATE_TUNNEL); - } - - ASSERT (0); - return (GBP_VXLAN_TEMPLATE_TUNNEL); -} - -gbp_itf_hdl_t -gbp_vxlan_tunnel_clone_and_lock (u32 sw_if_index, - const ip46_address_t * src, - const ip46_address_t * dst) -{ - gbp_vxlan_tunnel_t *gt; - index_t gti; - - gti = gbp_vxlan_tunnel_db[sw_if_index]; - - if (INDEX_INVALID == gti) - return (GBP_ITF_HDL_INVALID); - - gt = pool_elt_at_index (gbp_vxlan_tunnel_pool, gti); - - return (gdb_vxlan_dep_add (gt, src, dst)); -} - -void -vxlan_gbp_tunnel_unlock (u32 sw_if_index) -{ - /* vxlan_tunnel_ref_t *vxr; */ - /* index_t vxri; */ - - /* vxri = vxlan_tunnel_ref_db[sw_if_index]; */ - - /* ASSERT (vxri != INDEX_INVALID); */ - - /* vxr = vxlan_tunnel_ref_get (vxri); */ - - /* gdb_vxlan_dep_del (vxri); */ -} - -void -gbp_vxlan_walk (gbp_vxlan_cb_t cb, void *ctx) -{ - gbp_vxlan_tunnel_t *gt; - - /* *INDENT-OFF* */ - pool_foreach (gt, gbp_vxlan_tunnel_pool) - { - if (WALK_CONTINUE != cb(gt, ctx)) - break; - } - /* *INDENT-ON* */ -} - -static walk_rc_t -gbp_vxlan_tunnel_show_one (gbp_vxlan_tunnel_t * gt, void *ctx) -{ - vlib_cli_output (ctx, "%U", format_gbp_vxlan_tunnel, - gt - gbp_vxlan_tunnel_pool); - - return (WALK_CONTINUE); -} - -static u8 * -format_gbp_vxlan_tunnel_name (u8 * s, va_list * args) -{ - u32 dev_instance = va_arg (*args, u32); - - return format (s, "gbp-vxlan-%d", dev_instance); -} - -u8 * -format_gbp_vxlan_tunnel_layer (u8 * s, va_list * args) -{ - gbp_vxlan_tunnel_layer_t gl = va_arg (*args, gbp_vxlan_tunnel_layer_t); - s = format (s, "%s", gbp_vxlan_tunnel_layer_strings[gl]); - - return (s); -} - -u8 * -format_gbp_vxlan_tunnel (u8 * s, va_list * args) -{ - u32 dev_instance = va_arg (*args, u32); - CLIB_UNUSED (int verbose) = va_arg (*args, int); - gbp_vxlan_tunnel_t *gt = gbp_vxlan_tunnel_get (dev_instance); - index_t *vxri; - - s = format (s, " [%d] gbp-vxlan-tunnel: hw:%d sw:%d vni:%d %U", - dev_instance, gt->gt_hw_if_index, - gt->gt_sw_if_index, gt->gt_vni, - format_gbp_vxlan_tunnel_layer, gt->gt_layer); - if (GBP_VXLAN_TUN_L2 == gt->gt_layer) - s = format (s, " BD:%d gbd-index:%d", gt->gt_bd_rd_id, gt->gt_gbd); - else - s = format (s, " RD:%d grd-index:%d", gt->gt_bd_rd_id, gt->gt_grd); - - s = format (s, " dependents:"); - vec_foreach (vxri, gt->gt_tuns) - { - s = format (s, "\n %U, ", format_vxlan_tunnel_ref, *vxri); - } - - return s; -} - -typedef struct gbp_vxlan_tx_trace_t_ -{ - u32 vni; -} gbp_vxlan_tx_trace_t; - -u8 * -format_gbp_vxlan_tx_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - gbp_vxlan_tx_trace_t *t = va_arg (*args, gbp_vxlan_tx_trace_t *); - - s = format (s, "GBP-VXLAN: vni:%d", t->vni); - - return (s); -} - -clib_error_t * -gbp_vxlan_interface_admin_up_down (vnet_main_t * vnm, - u32 hw_if_index, u32 flags) -{ - vnet_hw_interface_t *hi; - u32 ti; - - hi = vnet_get_hw_interface (vnm, hw_if_index); - - if (NULL == gbp_vxlan_tunnel_db || - hi->sw_if_index >= vec_len (gbp_vxlan_tunnel_db)) - return (NULL); - - ti = gbp_vxlan_tunnel_db[hi->sw_if_index]; - - if (~0 == ti) - /* not one of ours */ - return (NULL); - - if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) - vnet_hw_interface_set_flags (vnm, hw_if_index, - VNET_HW_INTERFACE_FLAG_LINK_UP); - else - vnet_hw_interface_set_flags (vnm, hw_if_index, 0); - - return (NULL); -} - -static uword -gbp_vxlan_interface_tx (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) -{ - clib_warning ("you shouldn't be here, leaking buffers..."); - return frame->n_vectors; -} - -/* *INDENT-OFF* */ -VNET_DEVICE_CLASS (gbp_vxlan_device_class) = { - .name = "GBP VXLAN tunnel-template", - .format_device_name = format_gbp_vxlan_tunnel_name, - .format_device = format_gbp_vxlan_tunnel, - .format_tx_trace = format_gbp_vxlan_tx_trace, - .admin_up_down_function = gbp_vxlan_interface_admin_up_down, - .tx_function = gbp_vxlan_interface_tx, -}; - -VNET_HW_INTERFACE_CLASS (gbp_vxlan_hw_interface_class) = { - .name = "GBP-VXLAN", - .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P, -}; -/* *INDENT-ON* */ - -int -gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer, - u32 bd_rd_id, - const ip4_address_t * src, u32 * sw_if_indexp) -{ - gbp_vxlan_tunnel_t *gt; - index_t gti; - uword *p; - int rv; - - rv = 0; - p = hash_get (gv_db, vni); - - GBP_VXLAN_TUN_DBG ("add: %d %d %d", vni, layer, bd_rd_id); - - if (NULL == p) - { - vnet_sw_interface_t *si; - vnet_hw_interface_t *hi; - index_t gbi, grdi; - vnet_main_t *vnm; - - gbi = grdi = INDEX_INVALID; - - if (layer == GBP_VXLAN_TUN_L2) - { - gbi = gbp_bridge_domain_find_and_lock (bd_rd_id); - - if (INDEX_INVALID == gbi) - { - return (VNET_API_ERROR_BD_NOT_MODIFIABLE); - } - } - else - { - grdi = gbp_route_domain_find_and_lock (bd_rd_id); - - if (INDEX_INVALID == grdi) - { - return (VNET_API_ERROR_NO_SUCH_FIB); - } - } - - vnm = vnet_get_main (); - pool_get (gbp_vxlan_tunnel_pool, gt); - gti = gt - gbp_vxlan_tunnel_pool; - - gt->gt_vni = vni; - gt->gt_layer = layer; - gt->gt_bd_rd_id = bd_rd_id; - gt->gt_src.ip4.as_u32 = src->as_u32; - gt->gt_hw_if_index = vnet_register_interface (vnm, - gbp_vxlan_device_class.index, - gti, - gbp_vxlan_hw_interface_class.index, - gti); - - hi = vnet_get_hw_interface (vnm, gt->gt_hw_if_index); - - gt->gt_sw_if_index = hi->sw_if_index; - - /* don't flood packets in a BD to these interfaces */ - si = vnet_get_sw_interface (vnm, gt->gt_sw_if_index); - si->flood_class = VNET_FLOOD_CLASS_NO_FLOOD; - - if (layer == GBP_VXLAN_TUN_L2) - { - gbp_bridge_domain_t *gb; - - gb = gbp_bridge_domain_get (gbi); - - gt->gt_gbd = gbi; - gb->gb_vni = gti; - /* set it up as a GBP interface */ - gt->gt_itf = gbp_itf_l2_add_and_lock (gt->gt_sw_if_index, - gt->gt_gbd); - gbp_itf_l2_set_input_feature (gt->gt_itf, L2INPUT_FEAT_GBP_LEARN); - } - else - { - gt->gt_grd = grdi; - gt->gt_itf = gbp_itf_l3_add_and_lock (gt->gt_sw_if_index, - gt->gt_grd); - gbp_itf_l3_set_input_feature (gt->gt_itf, GBP_ITF_L3_FEAT_LEARN); - } - - /* - * save the tunnel by VNI and by sw_if_index - */ - hash_set (gv_db, vni, gti); - - vec_validate_init_empty (gbp_vxlan_tunnel_db, - gt->gt_sw_if_index, INDEX_INVALID); - gbp_vxlan_tunnel_db[gt->gt_sw_if_index] = gti; - - if (sw_if_indexp) - *sw_if_indexp = gt->gt_sw_if_index; - - vxlan_gbp_register_udp_ports (); - } - else - { - gti = p[0]; - rv = VNET_API_ERROR_IF_ALREADY_EXISTS; - } - - GBP_VXLAN_TUN_DBG ("add: %U", format_gbp_vxlan_tunnel, gti); - - return (rv); -} - -int -gbp_vxlan_tunnel_del (u32 vni) -{ - gbp_vxlan_tunnel_t *gt; - uword *p; - - p = hash_get (gv_db, vni); - - if (NULL != p) - { - vnet_main_t *vnm; - - vnm = vnet_get_main (); - gt = gbp_vxlan_tunnel_get (p[0]); - - vxlan_gbp_unregister_udp_ports (); - - GBP_VXLAN_TUN_DBG ("del: %U", format_gbp_vxlan_tunnel, - gt - gbp_vxlan_tunnel_pool); - - gbp_endpoint_flush (GBP_ENDPOINT_SRC_DP, gt->gt_sw_if_index); - ASSERT (0 == vec_len (gt->gt_tuns)); - vec_free (gt->gt_tuns); - - gbp_itf_unlock (>->gt_itf); - - if (GBP_VXLAN_TUN_L2 == gt->gt_layer) - { - gbp_bridge_domain_unlock (gt->gt_gbd); - } - else - { - gbp_route_domain_unlock (gt->gt_grd); - } - - vnet_sw_interface_set_flags (vnm, gt->gt_sw_if_index, 0); - vnet_delete_hw_interface (vnm, gt->gt_hw_if_index); - - hash_unset (gv_db, vni); - gbp_vxlan_tunnel_db[gt->gt_sw_if_index] = INDEX_INVALID; - - pool_put (gbp_vxlan_tunnel_pool, gt); - } - else - return VNET_API_ERROR_NO_SUCH_ENTRY; - - return (0); -} - -static clib_error_t * -gbp_vxlan_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - - vlib_cli_output (vm, "GBP-VXLAN Interfaces:"); - - gbp_vxlan_walk (gbp_vxlan_tunnel_show_one, vm); - - return (NULL); -} - -/*? - * Show Group Based Policy VXLAN tunnels - * - * @cliexpar - * @cliexstart{show gbp vxlan} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gbp_vxlan_show_node, static) = { - .path = "show gbp vxlan", - .short_help = "show gbp vxlan\n", - .function = gbp_vxlan_show, -}; -/* *INDENT-ON* */ - -static clib_error_t * -gbp_vxlan_init (vlib_main_t * vm) -{ - vxlan_gbp_main_t *vxm = &vxlan_gbp_main; - - gt_logger = vlib_log_register_class ("gbp", "tun"); - - punt_hdl = vlib_punt_client_register ("gbp-vxlan"); - - vlib_punt_register (punt_hdl, - vxm->punt_no_such_tunnel[FIB_PROTOCOL_IP4], - "gbp-vxlan4"); - - return (0); -} - -/* *INDENT-OFF* */ -VLIB_INIT_FUNCTION (gbp_vxlan_init) = -{ - .runs_after = VLIB_INITS("punt_init", "vxlan_gbp_init"), -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_vxlan.h b/src/plugins/gbp/gbp_vxlan.h deleted file mode 100644 index 706fe2a0e85..00000000000 --- a/src/plugins/gbp/gbp_vxlan.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef __GBP_VXLAN_H__ -#define __GBP_VXLAN_H__ - -#include <vnet/fib/fib_types.h> -#include <plugins/gbp/gbp_itf.h> - -#define foreach_gbp_vxlan_tunnel_layer \ - _ (L2, "l2") \ - _ (L3, "l3") - -typedef enum gbp_vxlan_tunnel_layer_t_ -{ -#define _(s,n) GBP_VXLAN_TUN_##s, - foreach_gbp_vxlan_tunnel_layer -#undef _ -} gbp_vxlan_tunnel_layer_t; - -/** - * GBP VXLAN (template) tunnel. - * A template tunnel has only a VNI, it does not have src,dst address. - * As such it cannot be used to send traffic. It is used in the RX path - * to RX vxlan-gbp packets that do not match an existing tunnel; - */ -typedef struct gbp_vxlan_tunnel_t_ -{ - u32 gt_hw_if_index; - u32 gt_sw_if_index; - u32 gt_vni; - - /** - * The BD or RD value (depending on the layer) that the tunnel is bound to - */ - u32 gt_bd_rd_id; - gbp_vxlan_tunnel_layer_t gt_layer; - - union - { - struct - { - /** - * Reference to the GPB-BD - */ - index_t gt_gbd; - }; - struct - { - /** - * References to the GBP-RD - */ - index_t gt_grd; - }; - }; - - /** - * gbp-itf config for this interface - */ - gbp_itf_hdl_t gt_itf; - - /** - * list of child vxlan-gbp tunnels built from this template - */ - index_t *gt_tuns; - - /** - * The source address to use for child tunnels - */ - ip46_address_t gt_src; -} gbp_vxlan_tunnel_t; - -/** - * The different types of interfaces that endpoints are learned on - */ -typedef enum gbp_vxlan_tunnel_type_t_ -{ - /** - * This is the object type defined above. - * A template representation of a vxlan-gbp tunnel. from this tunnel - * type, real vxlan-gbp tunnels are created (by cloning the VNI) - */ - GBP_VXLAN_TEMPLATE_TUNNEL, - - /** - * A real VXLAN-GBP tunnel (from vnet/vxlan-gbp/...) - */ - VXLAN_GBP_TUNNEL, -} gbp_vxlan_tunnel_type_t; - -extern int gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer, - u32 bd_rd_id, - const ip4_address_t * src, - u32 * sw_if_indexp); -extern int gbp_vxlan_tunnel_del (u32 vni); - -extern gbp_vxlan_tunnel_type_t gbp_vxlan_tunnel_get_type (u32 sw_if_index); - -extern gbp_itf_hdl_t gbp_vxlan_tunnel_clone_and_lock (u32 parent_tunnel, - const ip46_address_t * - src, - const ip46_address_t * - dst); - -extern u32 vxlan_gbp_tunnel_get_parent (u32 sw_if_index); -extern gbp_itf_hdl_t vxlan_gbp_tunnel_lock_itf (u32 sw_if_index); - -typedef walk_rc_t (*gbp_vxlan_cb_t) (gbp_vxlan_tunnel_t * gt, void *ctx); -extern void gbp_vxlan_walk (gbp_vxlan_cb_t cb, void *ctx); - -extern u8 *format_gbp_vxlan_tunnel (u8 * s, va_list * args); -extern u8 *format_gbp_vxlan_tunnel_layer (u8 * s, va_list * args); - -extern gbp_vxlan_tunnel_t *gbp_vxlan_tunnel_get (index_t gti); -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/gbp/gbp_vxlan_node.c b/src/plugins/gbp/gbp_vxlan_node.c deleted file mode 100644 index 413a9f47e1b..00000000000 --- a/src/plugins/gbp/gbp_vxlan_node.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2019 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. - */ -#include <plugins/gbp/gbp_vxlan.h> -#include <plugins/gbp/gbp_itf.h> -#include <plugins/gbp/gbp_learn.h> -#include <plugins/gbp/gbp_bridge_domain.h> -#include <plugins/gbp/gbp_route_domain.h> - -#include <vnet/vxlan-gbp/vxlan_gbp.h> -#include <vlibmemory/api.h> -#include <vnet/fib/fib_table.h> - -extern uword *gv_db; - -typedef struct gbp_vxlan_trace_t_ -{ - u8 dropped; - u32 vni; - u32 sw_if_index; - u16 sclass; - u8 flags; -} gbp_vxlan_trace_t; - -#define foreach_gbp_vxlan_input_next \ - _(DROP, "error-drop") \ - _(L2_INPUT, "l2-input") \ - _(IP4_INPUT, "ip4-input") \ - _(IP6_INPUT, "ip6-input") - -typedef enum -{ -#define _(s,n) GBP_VXLAN_INPUT_NEXT_##s, - foreach_gbp_vxlan_input_next -#undef _ - GBP_VXLAN_INPUT_N_NEXT, -} gbp_vxlan_input_next_t; - - -#define foreach_gbp_vxlan_error \ - _(DECAPPED, "decapped") \ - _(LEARNED, "learned") - -typedef enum -{ -#define _(s,n) GBP_VXLAN_ERROR_##s, - foreach_gbp_vxlan_error -#undef _ - GBP_VXLAN_N_ERROR, -} gbp_vxlan_input_error_t; - -static char *gbp_vxlan_error_strings[] = { -#define _(n,s) s, - foreach_gbp_vxlan_error -#undef _ -}; - -static uword -gbp_vxlan_decap (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame, u8 is_ip4) -{ - u32 n_left_to_next, n_left_from, next_index, *to_next, *from; - - next_index = 0; - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - - while (n_left_from > 0) - { - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - vxlan_gbp_header_t *vxlan_gbp0; - gbp_vxlan_input_next_t next0; - gbp_vxlan_tunnel_t *gt0; - vlib_buffer_t *b0; - u32 bi0, vni0; - uword *p; - - bi0 = to_next[0] = from[0]; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - next0 = GBP_VXLAN_INPUT_NEXT_DROP; - - b0 = vlib_get_buffer (vm, bi0); - vxlan_gbp0 = - vlib_buffer_get_current (b0) - sizeof (vxlan_gbp_header_t); - - vni0 = vxlan_gbp_get_vni (vxlan_gbp0); - p = hash_get (gv_db, vni0); - - if (PREDICT_FALSE (NULL == p)) - { - gt0 = NULL; - next0 = GBP_VXLAN_INPUT_NEXT_DROP; - } - else - { - gt0 = gbp_vxlan_tunnel_get (p[0]); - - vnet_buffer (b0)->sw_if_index[VLIB_RX] = gt0->gt_sw_if_index; - - if (GBP_VXLAN_TUN_L2 == gt0->gt_layer) - /* - * An L2 layer tunnel goes into the BD - */ - next0 = GBP_VXLAN_INPUT_NEXT_L2_INPUT; - else - { - /* - * An L3 layer tunnel needs to strip the L2 header - * an inject into the RD - */ - ethernet_header_t *e0; - u16 type0; - - e0 = vlib_buffer_get_current (b0); - type0 = clib_net_to_host_u16 (e0->type); - switch (type0) - { - case ETHERNET_TYPE_IP4: - next0 = GBP_VXLAN_INPUT_NEXT_IP4_INPUT; - break; - case ETHERNET_TYPE_IP6: - next0 = GBP_VXLAN_INPUT_NEXT_IP6_INPUT; - break; - default: - goto trace; - } - vlib_buffer_advance (b0, sizeof (*e0)); - } - } - - trace: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - gbp_vxlan_trace_t *tr; - - tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); - tr->dropped = (next0 == GBP_VXLAN_INPUT_NEXT_DROP); - tr->vni = vni0; - tr->sw_if_index = (gt0 ? gt0->gt_sw_if_index : ~0); - tr->flags = vxlan_gbp_get_gpflags (vxlan_gbp0); - tr->sclass = vxlan_gbp_get_sclass (vxlan_gbp0); - } - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return from_frame->n_vectors; -} - -VLIB_NODE_FN (gbp_vxlan4_input_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - return gbp_vxlan_decap (vm, node, from_frame, 1); -} - -static u8 * -format_gbp_vxlan_rx_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - gbp_vxlan_trace_t *t = va_arg (*args, gbp_vxlan_trace_t *); - - s = format (s, "vni:%d dropped:%d rx:%d sclass:%d flags:%U", - t->vni, t->dropped, t->sw_if_index, - t->sclass, format_vxlan_gbp_header_gpflags, t->flags); - - return (s); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (gbp_vxlan4_input_node) = -{ - .name = "gbp-vxlan4", - .vector_size = sizeof (u32), - .n_errors = GBP_VXLAN_N_ERROR, - .error_strings = gbp_vxlan_error_strings, - .n_next_nodes = GBP_VXLAN_INPUT_N_NEXT, - .format_trace = format_gbp_vxlan_rx_trace, - .next_nodes = { -#define _(s,n) [GBP_VXLAN_INPUT_NEXT_##s] = n, - foreach_gbp_vxlan_input_next -#undef _ - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/l2e/CMakeLists.txt b/src/plugins/l2e/CMakeLists.txt deleted file mode 100644 index 2bfb05a43e6..00000000000 --- a/src/plugins/l2e/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2018 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. - -add_vpp_plugin(l2e - SOURCES - l2e_node.c - l2e_api.c - l2e.c - - MULTIARCH_SOURCES - l2e_node.c - - API_FILES - l2e.api - - INSTALL_HEADERS - l2e.h -) diff --git a/src/plugins/l2e/l2e.api b/src/plugins/l2e/l2e.api deleted file mode 100644 index 586e2bae5ca..00000000000 --- a/src/plugins/l2e/l2e.api +++ /dev/null @@ -1,39 +0,0 @@ -/* Hey Emacs use -*- mode: C -*- */ -/* - * 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. - */ - -option version = "1.0.0"; -import "vnet/interface_types.api"; - -/** \brief L2 emulation at L3 - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param sw_if_index - interface the operation is applied to - @param enable - Turn the service on or off -*/ -autoreply define l2_emulation -{ - option status="in_progress"; - u32 client_index; - u32 context; - vl_api_interface_index_t sw_if_index; - bool enable; -}; - -/* - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/l2e/l2e.c b/src/plugins/l2e/l2e.c deleted file mode 100644 index 4c6eac50446..00000000000 --- a/src/plugins/l2e/l2e.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * l2e.c : Extract L3 packets from the L2 input and feed - * them into the L3 path. - * - * Copyright (c) 2013 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. - */ - -#include <plugins/l2e/l2e.h> -#include <vnet/l2/l2_input.h> -#include <vnet/l2/feat_bitmap.h> -#include <vnet/ip/ip.h> - -l2_emulation_main_t l2_emulation_main; - -/** - * A zero'd out struct we can use in the vec_validate - */ -static const l2_emulation_t ezero = { }; - -__clib_export void -l2_emulation_enable (u32 sw_if_index) -{ - l2_emulation_main_t *em = &l2_emulation_main; - vec_validate_init_empty (em->l2_emulations, sw_if_index, ezero); - - l2_emulation_t *l23e = &em->l2_emulations[sw_if_index]; - - l23e->enabled = 1; - - /* - * L3 enable the interface - using IP unnumbered from the control - * plane may not be possible since there may be no BVI interface - * to which to unnumber - */ - ip4_sw_interface_enable_disable (sw_if_index, 1); - ip6_sw_interface_enable_disable (sw_if_index, 1); - - l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_L2_EMULATION, 1); -} - - -__clib_export void -l2_emulation_disable (u32 sw_if_index) -{ - l2_emulation_main_t *em = &l2_emulation_main; - if (vec_len (em->l2_emulations) >= sw_if_index) - { - l2_emulation_t *l23e = &em->l2_emulations[sw_if_index]; - clib_memset (l23e, 0, sizeof (*l23e)); - - l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_L2_EMULATION, 0); - ip4_sw_interface_enable_disable (sw_if_index, 0); - ip6_sw_interface_enable_disable (sw_if_index, 0); - } -} - -static clib_error_t * -l2_emulation_interface_add_del (vnet_main_t * vnm, - u32 sw_if_index, u32 is_add) -{ - l2_emulation_main_t *em = &l2_emulation_main; - if (is_add) - { - vec_validate_init_empty (em->l2_emulations, sw_if_index, ezero); - } - - return (NULL); -} - -VNET_SW_INTERFACE_ADD_DEL_FUNCTION (l2_emulation_interface_add_del); - -static clib_error_t * -l2_emulation_cli (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - vnet_main_t *vnm = vnet_get_main (); - u32 sw_if_index = ~0; - u8 enable = 1; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "%U", unformat_vnet_sw_interface, - vnm, &sw_if_index)) - ; - else if (unformat (input, "enable")) - enable = 1; - else if (unformat (input, "disable")) - enable = 0; - else - break; - } - - if (~0 == sw_if_index) - return clib_error_return (0, "interface must be specified"); - - if (enable) - l2_emulation_enable (sw_if_index); - else - l2_emulation_disable (sw_if_index); - - return (NULL); -} - -/*? - * Configure l2 emulation. - * When the interface is in L2 mode, configure the extraction of L3 - * packets out of the L2 path and into the L3 path. - * - * @cliexpar - * @cliexstart{set interface l2 input l2-emulation <interface-name> [disable]} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (l2_emulation_cli_node, static) = { - .path = "set interface l2 l2-emulation", - .short_help = - "set interface l2 l2-emulation <interface-name> [disable|enable]\n", - .function = l2_emulation_cli, -}; -/* *INDENT-ON* */ - -static clib_error_t * -l2_emulation_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - l2_emulation_main_t *em = &l2_emulation_main; - vnet_main_t *vnm = vnet_get_main (); - l2_emulation_t *l23e; - u32 sw_if_index; - - vec_foreach_index (sw_if_index, em->l2_emulations) - { - l23e = &em->l2_emulations[sw_if_index]; - if (l23e->enabled) - { - vlib_cli_output (vm, "%U\n", - format_vnet_sw_if_index_name, vnm, sw_if_index); - } - } - return (NULL); -} - -/*? - * Show l2 emulation. - * When the interface is in L2 mode, configure the extraction of L3 - * packets out of the L2 path and into the L3 path. - * - * @cliexpar - * @cliexstart{show interface l2 l2-emulation} - * @cliexend - ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (l2_emulation_show_node, static) = { - .path = "show interface l2 l2-emulation", - .short_help = "show interface l2 l2-emulation\n", - .function = l2_emulation_show, -}; -/* *INDENT-ON* */ - -static clib_error_t * -l2_emulation_init (vlib_main_t * vm) -{ - l2_emulation_main_t *em = &l2_emulation_main; - vlib_node_t *node; - - node = vlib_get_node_by_name (vm, (u8 *) "l2-emulation"); - em->l2_emulation_node_index = node->index; - - /* Initialize the feature next-node indexes */ - feat_bitmap_init_next_nodes (vm, - em->l2_emulation_node_index, - L2INPUT_N_FEAT, - l2input_get_feat_names (), - em->l2_input_feat_next); - - return 0; -} - -VLIB_INIT_FUNCTION (l2_emulation_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/l2e/l2e.h b/src/plugins/l2e/l2e.h deleted file mode 100644 index e548d333f9d..00000000000 --- a/src/plugins/l2e/l2e.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2013 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. - */ - -#ifndef included_vnet_l2_emulation_h -#define included_vnet_l2_emulation_h - -#include <vlib/vlib.h> -#include <vnet/vnet.h> - -/** - * Per-interface L2 configuration - */ -typedef struct l2_emulation_t_ -{ - /** - * Enabled or Disabled. - * this is required since one L3 protocl can be enabled, but others not - */ - u8 enabled; -} l2_emulation_t; - -/** - * per-packet trace data - */ -typedef struct l2_emulation_trace_t_ -{ - /* per-pkt trace data */ - u8 extracted; -} l2_emulation_trace_t; - -/** - * Grouping of global data for the L2 emulation feature - */ -typedef struct l2_emulation_main_t_ -{ - u16 msg_id_base; - - u32 l2_emulation_node_index; - - /** - * Per-interface vector of emulation configs - */ - l2_emulation_t *l2_emulations; - - /** - * Next nodes for L2 output features - */ - u32 l2_input_feat_next[32]; -} l2_emulation_main_t; - -/** - * L2 Emulation is a feautre that is applied to L2 ports to 'extract' - * IP packets from the L2 path and inject them into the L3 path (i.e. - * into the appropriate ip[4|6]_input node). - * L3 routes in the table_id for that interface should then be configured - * as DVR routes, therefore the forwarded packet has the L2 header - * preserved and togehter the L3 routed system behaves like an L2 bridge. - */ -extern void l2_emulation_enable (u32 sw_if_index); -extern void l2_emulation_disable (u32 sw_if_index); - -extern l2_emulation_main_t l2_emulation_main; - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/l2e/l2e_api.c b/src/plugins/l2e/l2e_api.c deleted file mode 100644 index fe2fb7ee06e..00000000000 --- a/src/plugins/l2e/l2e_api.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - *------------------------------------------------------------------ - * l2e_api.c - layer 2 emulation api - * - * 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. - *------------------------------------------------------------------ - */ - -#include <vnet/vnet.h> -#include <vnet/plugin/plugin.h> - -#include <vnet/interface.h> -#include <vnet/api_errno.h> -#include <vpp/app/version.h> - -#include <l2e/l2e.h> - -#include <vlibapi/api.h> -#include <vlibmemory/api.h> - -/* define message IDs */ -#include <l2e/l2e.api_enum.h> -#include <l2e/l2e.api_types.h> - -#include <vlibapi/api_helper_macros.h> - -#define L2E_MSG_BASE l2em->msg_id_base - -static void -vl_api_l2_emulation_t_handler (vl_api_l2_emulation_t * mp) -{ - l2_emulation_main_t *l2em = &l2_emulation_main; - vl_api_l2_emulation_reply_t *rmp; - int rv = 0; - - VALIDATE_SW_IF_INDEX (mp); - - u32 sw_if_index = ntohl (mp->sw_if_index); - - if (mp->enable) - l2_emulation_enable (sw_if_index); - else - l2_emulation_disable (sw_if_index); - - BAD_SW_IF_INDEX_LABEL; - - REPLY_MACRO (VL_API_L2_EMULATION_REPLY + L2E_MSG_BASE); -} - -#include <l2e/l2e.api.c> -static clib_error_t * -l2e_init (vlib_main_t * vm) -{ - l2_emulation_main_t *l2em = &l2_emulation_main; - - /* Ask for a correctly-sized block of API message decode slots */ - l2em->msg_id_base = setup_message_id_table (); - - return (NULL); -} - -VLIB_API_INIT_FUNCTION (l2e_init); - -/* *INDENT-OFF* */ -VLIB_PLUGIN_REGISTER () = { - .version = VPP_BUILD_VER, - .description = "Layer 2 (L2) Emulation", -}; -/* *INDENT-ON* */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/l2e/l2e_node.c b/src/plugins/l2e/l2e_node.c deleted file mode 100644 index 71c9b4bc6af..00000000000 --- a/src/plugins/l2e/l2e_node.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * l2e_node.c : l2 emulation node - * - * Copyright (c) 2019 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. - */ -#include <plugins/l2e/l2e.h> -#include <vnet/l2/l2_input.h> -#include <vnet/l2/feat_bitmap.h> - -#define foreach_l2_emulation \ - _(IP4, "Extract IPv4") \ - _(IP6, "Extract IPv6") - -typedef enum -{ -#define _(sym,str) L2_EMULATION_ERROR_##sym, - foreach_l2_emulation -#undef _ - L2_EMULATION_N_ERROR, -} l2_emulation_error_t; - -static char *l2_emulation_error_strings[] = { -#define _(sym,string) string, - foreach_l2_emulation -#undef _ -}; - -typedef enum -{ -#define _(sym,str) L2_EMULATION_NEXT_##sym, - foreach_l2_emulation -#undef _ - L2_EMULATION_N_NEXT, -} l2_emulation_next_t; - -/* packet trace format function */ -static u8 * -format_l2_emulation_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - l2_emulation_trace_t *t = va_arg (*args, l2_emulation_trace_t *); - - s = format (s, "l2-emulation: %s", (t->extracted ? "yes" : "no")); - - return s; -} - -VLIB_NODE_FN (l2_emulation_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - l2_emulation_main_t *em = &l2_emulation_main; - u32 n_left_from, *from, *to_next; - l2_emulation_next_t next_index; - u32 ip4_hits = 0; - u32 ip6_hits = 0; - - next_index = 0; - n_left_from = frame->n_vectors; - from = vlib_frame_vector_args (frame); - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - while (n_left_from >= 4 && n_left_to_next >= 2) - { - vlib_buffer_t *b0, *b1; - u32 sw_if_index0, sw_if_index1; - u16 ether_type0, ether_type1; - u32 next0 = ~0, next1 = ~0; - u8 l2_len0, l2_len1; - u32 bi0, bi1; - u8 *h0, *h1; - - bi0 = to_next[0] = from[0]; - bi1 = to_next[1] = from[1]; - - from += 2; - n_left_from -= 2; - to_next += 2; - n_left_to_next -= 2; - - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - l2_len0 = vnet_buffer (b0)->l2.l2_len; - l2_len1 = vnet_buffer (b1)->l2.l2_len; - - h0 = vlib_buffer_get_current (b0); - h1 = vlib_buffer_get_current (b1); - - ether_type0 = clib_net_to_host_u16 (*(u16 *) (h0 + l2_len0 - 2)); - ether_type1 = clib_net_to_host_u16 (*(u16 *) (h1 + l2_len1 - 2)); - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; - - /* - * only extract unicast - */ - if (PREDICT_TRUE (!(h0[0] & 0x1))) - { - switch (ether_type0) - { - case ETHERNET_TYPE_IP4: - ASSERT (em->l2_emulations[sw_if_index0].enabled); - ++ip4_hits; - next0 = L2_EMULATION_NEXT_IP4; - vlib_buffer_advance (b0, l2_len0); - break; - case ETHERNET_TYPE_IP6: - ASSERT (em->l2_emulations[sw_if_index0].enabled); - ++ip6_hits; - next0 = L2_EMULATION_NEXT_IP6; - vlib_buffer_advance (b0, l2_len0); - default: - break; - } - } - if (PREDICT_TRUE (!(h1[0] & 0x1))) - { - switch (ether_type1) - { - case ETHERNET_TYPE_IP4: - ASSERT (em->l2_emulations[sw_if_index1].enabled); - ++ip4_hits; - next1 = L2_EMULATION_NEXT_IP4; - vlib_buffer_advance (b1, l2_len1); - break; - case ETHERNET_TYPE_IP6: - ASSERT (em->l2_emulations[sw_if_index1].enabled); - ++ip6_hits; - next1 = L2_EMULATION_NEXT_IP6; - vlib_buffer_advance (b1, l2_len1); - default: - break; - } - } - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) - && (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - l2_emulation_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->extracted = (next0 != ~0); - } - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) - && (b1->flags & VLIB_BUFFER_IS_TRACED))) - { - l2_emulation_trace_t *t = - vlib_add_trace (vm, node, b1, sizeof (*t)); - t->extracted = (next1 != ~0); - } - - /* Determine the next node and remove ourself from bitmap */ - if (PREDICT_TRUE (next0 == ~0)) - next0 = vnet_l2_feature_next (b0, em->l2_input_feat_next, - L2INPUT_FEAT_L2_EMULATION); - - /* Determine the next node and remove ourself from bitmap */ - if (PREDICT_TRUE (next1 == ~0)) - next1 = vnet_l2_feature_next (b1, em->l2_input_feat_next, - L2INPUT_FEAT_L2_EMULATION); - - vlib_validate_buffer_enqueue_x2 (vm, node, next_index, - to_next, n_left_to_next, - bi0, bi1, next0, next1); - } - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u32 sw_if_index0; - u16 ether_type0; - u32 next0 = ~0; - u8 l2_len0; - u32 bi0; - u8 *h0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - l2_len0 = vnet_buffer (b0)->l2.l2_len; - - h0 = vlib_buffer_get_current (b0); - ether_type0 = clib_net_to_host_u16 (*(u16 *) (h0 + l2_len0 - 2)); - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - - /* - * only extract unicast - */ - if (PREDICT_TRUE (!(h0[0] & 0x1))) - { - switch (ether_type0) - { - case ETHERNET_TYPE_IP4: - ASSERT (em->l2_emulations[sw_if_index0].enabled); - ++ip4_hits; - next0 = L2_EMULATION_NEXT_IP4; - vlib_buffer_advance (b0, l2_len0); - break; - case ETHERNET_TYPE_IP6: - ASSERT (em->l2_emulations[sw_if_index0].enabled); - ++ip6_hits; - next0 = L2_EMULATION_NEXT_IP6; - vlib_buffer_advance (b0, l2_len0); - default: - break; - } - } - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) - && (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - l2_emulation_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->extracted = (next0 != ~0); - } - - /* Determine the next node and remove ourself from bitmap */ - if (PREDICT_TRUE (next0 == ~0)) - next0 = vnet_l2_feature_next (b0, em->l2_input_feat_next, - L2INPUT_FEAT_L2_EMULATION); - - /* verify speculative enqueue, maybe switch current next frame */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - L2_EMULATION_ERROR_IP4, ip4_hits); - vlib_node_increment_counter (vm, node->node_index, - L2_EMULATION_ERROR_IP6, ip6_hits); - - return frame->n_vectors; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (l2_emulation_node) = { - .name = "l2-emulation", - .vector_size = sizeof (u32), - .format_trace = format_l2_emulation_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(l2_emulation_error_strings), - .error_strings = l2_emulation_error_strings, - - .n_next_nodes = L2_EMULATION_N_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [L2_EMULATION_NEXT_IP4] = "ip4-input", - [L2_EMULATION_NEXT_IP6] = "ip6-input", - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |