| /* |
| * Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. |
| * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for any |
| * purpose with or without fee is hereby granted, provided that the above |
| * copyright notice and this permission notice appear in all copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| #include "ecm_sfe_common_public.h" |
| |
| /* |
| * Export the callback object for frontend usage. |
| */ |
| extern struct ecm_sfe_common_callbacks ecm_sfe_cb; |
| |
| #ifdef CONFIG_XFRM |
| /* |
| * Which type of ipsec process traffic need. |
| */ |
| enum ecm_sfe_ipsec_state { |
| ECM_SFE_IPSEC_STATE_NONE = 0, |
| ECM_SFE_IPSEC_STATE_TO_ENCRYPT, |
| ECM_SFE_IPSEC_STATE_WAS_DECRYPTED |
| }; |
| #endif |
| |
| /* |
| * This macro converts ECM ip_addr_t to SFE IPv6 address |
| */ |
| #define ECM_IP_ADDR_TO_SFE_IPV6_ADDR(sfe6, ipaddrt) \ |
| { \ |
| ecm_type_check_ae_ipv6(sfe6); \ |
| ecm_type_check_ecm_ip_addr(ipaddrt); \ |
| sfe6[0] = htonl(ipaddrt[3]); \ |
| sfe6[1] = htonl(ipaddrt[2]); \ |
| sfe6[2] = htonl(ipaddrt[1]); \ |
| sfe6[3] = htonl(ipaddrt[0]); \ |
| } |
| |
| /* |
| * This macro converts SFE IPv6 address to ECM ip_addr_t |
| */ |
| #define ECM_SFE_IPV6_ADDR_TO_IP_ADDR(ipaddrt, sfe6) \ |
| { \ |
| ecm_type_check_ecm_ip_addr(ipaddrt); \ |
| ecm_type_check_ae_ipv6(sfe6); \ |
| ipaddrt[0] = ntohl(sfe6[3]); \ |
| ipaddrt[1] = ntohl(sfe6[2]); \ |
| ipaddrt[2] = ntohl(sfe6[1]); \ |
| ipaddrt[3] = ntohl(sfe6[0]); \ |
| } |
| |
| /* |
| * Common information |
| */ |
| struct ecm_sfe_common_fe_info { |
| uint32_t from_stats_bitmap; /* Bitmap of L2 features enabled for from direction */ |
| uint32_t to_stats_bitmap; /* Bitmap of L2 features enabled for to direction */ |
| }; |
| |
| /* |
| * ecm_sfe_feature_check() |
| * Check some specific features for SFE acceleration |
| */ |
| static inline bool ecm_sfe_feature_check(struct sk_buff *skb, struct ecm_tracker_ip_header *ip_hdr, bool is_routed) |
| { |
| if (!is_routed && !sfe_is_l2_feature_enabled()) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /* |
| * ecm_sfe_common_get_interface_number_by_dev() |
| * Returns the acceleration engine interface number based on the net_device object. |
| */ |
| static inline int32_t ecm_sfe_common_get_interface_number_by_dev(struct net_device *dev) |
| { |
| /* |
| * sfe_interface_num for all IPsec tunnels will always be the one specific to acceleration engine. |
| */ |
| if (dev->type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) { |
| return SFE_SPECIAL_INTERFACE_IPSEC; |
| } |
| |
| return dev->ifindex; |
| } |
| |
| /* |
| * ecm_sfe_common_get_interface_number_by_dev_type() |
| * Returns the acceleration engine interface number based on the net_device object and type. |
| */ |
| static inline int32_t ecm_sfe_common_get_interface_number_by_dev_type(struct net_device *dev, uint32_t type) |
| { |
| |
| return ecm_sfe_common_get_interface_number_by_dev(dev); |
| } |
| |
| /* |
| * ecm_sfe_common_connection_regenerate() |
| * Re-generate a specific connection in SFE front end |
| */ |
| static inline void ecm_sfe_common_connection_regenerate(struct ecm_front_end_connection_instance *feci, struct ecm_db_connection_instance *ci) |
| { |
| /* |
| * Flag the connection as needing re-generation. |
| * Re-generation occurs when we next see traffic OR an acceleration engine sync for this connection. |
| * Refer to front end protocol specific process() functions. |
| */ |
| ecm_db_connection_regeneration_needed(ci); |
| |
| /* |
| * If the connection is accelerated then force deceleration. |
| * Under normal circumstances deceleration would occur on the next sync received, |
| * however, there is a situation where a sync may not occur if, say, a cable has been pulled. |
| * The acceleration engine would see no further traffic to trigger sending a sync and so |
| * re-generation would not occur. |
| * The connection would stall and no-regeneration would happen leaving the connection in bad state. |
| * NOTE: We can just call decelerate() upon the front end - if its not accelerated this will have no effect. |
| */ |
| feci->decelerate(feci); |
| } |
| |
| /* |
| * ecm_sfe_common_get_interface_type() |
| * Gets the SFE interface type based on some features. |
| * |
| * NOTE: There is no type for SFE now. This function is implemented just to |
| * use it for the feci callback. |
| */ |
| static inline int32_t ecm_sfe_common_get_interface_type(struct ecm_front_end_connection_instance *feci, struct net_device *dev) |
| { |
| /* |
| * By default return 0. SFE driver doesn't have any interface type. |
| */ |
| return 0; |
| } |
| |
| bool ecm_sfe_common_fast_xmit_check(s32 interface_num); |
| bool ecm_sfe_ipv4_is_conn_limit_reached(void); |
| bool ecm_sfe_ipv6_is_conn_limit_reached(void); |
| bool ecm_sfe_common_is_l2_iface_supported(ecm_db_iface_type_t ii_type, int cur_heirarchy_index, int first_heirarchy_index); |
| |
| void ecm_sfe_common_init_fe_info(struct ecm_sfe_common_fe_info *info); |
| uint32_t ecm_sfe_common_get_stats_bitmap(struct ecm_sfe_common_fe_info *fe_info, ecm_db_obj_dir_t dir); |
| void ecm_sfe_common_set_stats_bitmap(struct ecm_sfe_common_fe_info *fe_info, ecm_db_obj_dir_t dir, uint8_t bit); |
| void ecm_sfe_common_update_rule(struct ecm_front_end_connection_instance *feci, enum ecm_rule_update_type type, void *arg); |
| void ecm_sfe_common_tuple_set(struct ecm_front_end_connection_instance *feci, |
| int32_t from_iface_id, int32_t to_iface_id, |
| struct ecm_sfe_common_tuple *tuple); |