diff --git a/shortcut-fe/simulated-driver/Makefile b/shortcut-fe/simulated-driver/Makefile index ecf9c41bd..0c710fe9d 100644 --- a/shortcut-fe/simulated-driver/Makefile +++ b/shortcut-fe/simulated-driver/Makefile @@ -30,7 +30,7 @@ define KernelPackage/shortcut-fe-drv SECTION:=kernel CATEGORY:=Kernel modules SUBMENU:=Network Support - DEPENDS:=@TARGET_ipq806x||TARGET_ipq807x +kmod-shortcut-fe + DEPENDS:=@TARGET_ipq60xx||@TARGET_ipq806x||TARGET_ipq807x +kmod-shortcut-fe KCONFIG:= \ CONFIG_NET_CLS_ACT=y \ CONFIG_XFRM=y diff --git a/simulated-driver/Makefile b/simulated-driver/Makefile deleted file mode 100755 index 39aa130f1..000000000 --- a/simulated-driver/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# Copyright (c) 2015 The Linux Foundation. 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. -# -# Makefile for Shortcut FE simulated driver. -# - -obj-m += shortcut-fe-drv.o - -shortcut-fe-drv-objs := \ - sfe_drv.o - diff --git a/simulated-driver/patches/200-nss-qdisc-support.patch b/simulated-driver/patches/200-nss-qdisc-support.patch deleted file mode 100755 index 638ad8a84..000000000 --- a/simulated-driver/patches/200-nss-qdisc-support.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- ./simulated-driver/sfe_drv.c.orig 2020-06-16 12:49:47.680153371 +0800 -+++ ./simulated-driver/sfe_drv.c 2020-06-16 12:50:18.540153371 +0800 -@@ -1167,7 +1167,7 @@ int sfe_drv_recv(struct sk_buff *skb) - * If ingress Qdisc configured, and packet not processed by ingress Qdisc yet - * We can not accelerate this packet. - */ -- if (dev->ingress_queue && !(skb->tc_verd & TC_NCLS)) { -+ if (dev->ingress_queue && !(skb->tc_verd_qca_nss & TC_NCLS)) { - return 0; - } - #endif diff --git a/simulated-driver/sfe_drv.c b/simulated-driver/sfe_drv.c deleted file mode 100644 index 98677d911..000000000 --- a/simulated-driver/sfe_drv.c +++ /dev/null @@ -1,1323 +0,0 @@ -/* - * sfe_drv.c - * simulated sfe driver for shortcut forwarding engine. - * - * Copyright (c) 2015,2016 The Linux Foundation. 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 -#include -#include -#include -#include -#include -#include - -#include "../shortcut-fe/sfe.h" -#include "../shortcut-fe/sfe_cm.h" -#include "sfe_drv.h" - -typedef enum sfe_drv_exception { - SFE_DRV_EXCEPTION_IPV4_MSG_UNKNOW, - SFE_DRV_EXCEPTION_IPV6_MSG_UNKNOW, - SFE_DRV_EXCEPTION_CONNECTION_INVALID, - SFE_DRV_EXCEPTION_NOT_SUPPORT_BRIDGE, - SFE_DRV_EXCEPTION_TCP_INVALID, - SFE_DRV_EXCEPTION_PROTOCOL_NOT_SUPPORT, - SFE_DRV_EXCEPTION_SRC_DEV_NOT_L3, - SFE_DRV_EXCEPTION_DEST_DEV_NOT_L3, - SFE_DRV_EXCEPTION_CREATE_FAILED, - SFE_DRV_EXCEPTION_ENQUEUE_FAILED, - SFE_DRV_EXCEPTION_NOT_SUPPORT_6RD, - SFE_DRV_EXCEPTION_NO_SYNC_CB, - SFE_DRV_EXCEPTION_MAX -} sfe_drv_exception_t; - -static char *sfe_drv_exception_events_string[SFE_DRV_EXCEPTION_MAX] = { - "IPV4_MSG_UNKNOW", - "IPV6_MSG_UNKNOW", - "CONNECTION_INVALID", - "NOT_SUPPORT_BRIDGE", - "TCP_INVALID", - "PROTOCOL_NOT_SUPPORT", - "SRC_DEV_NOT_L3", - "DEST_DEV_NOT_L3", - "CREATE_FAILED", - "ENQUEUE_FAILED", - "NOT_SUPPORT_6RD", - "NO_SYNC_CB" -}; - -#define SFE_MESSAGE_VERSION 0x1 -#define SFE_MAX_CONNECTION_NUM 65535 -#define sfe_drv_ipv6_addr_copy(src, dest) memcpy((void *)(dest), (void *)(src), 16) -#define sfe_drv_ipv4_stopped(CTX) (rcu_dereference((CTX)->ipv4_stats_sync_cb) == NULL) -#define sfe_drv_ipv6_stopped(CTX) (rcu_dereference((CTX)->ipv6_stats_sync_cb) == NULL) - -/* - * message type of queued response message - */ -typedef enum { - SFE_DRV_MSG_TYPE_IPV4, - SFE_DRV_MSG_TYPE_IPV6 -} sfe_drv_msg_types_t; - -/* - * queued response message, - * will be sent back to caller in workqueue - */ -struct sfe_drv_response_msg { - struct list_head node; - sfe_drv_msg_types_t type; - void *msg[0]; -}; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) -#define list_first_entry_or_null(ptr, type, member) \ - (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL) -#endif - -/* - * sfe driver context instance, private for sfe driver - */ -struct sfe_drv_ctx_instance_internal { - struct sfe_drv_ctx_instance base;/* exported sfe driver context, is public to user of sfe driver*/ - - /* - * Control state. - */ - struct kobject *sys_sfe_drv; /* sysfs linkage */ - - struct list_head msg_queue; /* response message queue*/ - spinlock_t lock; /* Lock to protect message queue */ - - struct work_struct work; /* work to send response message back to caller*/ - - sfe_ipv4_msg_callback_t __rcu ipv4_stats_sync_cb; /* callback to call to sync ipv4 statistics */ - void *ipv4_stats_sync_data; /* argument for above callback: ipv4_stats_sync_cb */ - - sfe_ipv6_msg_callback_t __rcu ipv6_stats_sync_cb; /* callback to call to sync ipv6 statistics */ - void *ipv6_stats_sync_data; /* argument for above callback: ipv6_stats_sync_cb */ - - u32 exceptions[SFE_DRV_EXCEPTION_MAX]; /* statistics for exception */ -}; - -static struct sfe_drv_ctx_instance_internal __sfe_drv_ctx; - -/* - * convert public sfe driver context to internal context - */ -#define SFE_DRV_CTX_TO_PRIVATE(base) (struct sfe_drv_ctx_instance_internal *)(base) -/* - * convert internal sfe driver context to public context - */ -#define SFE_DRV_CTX_TO_PUBLIC(intrv) (struct sfe_drv_ctx_instance *)(intrv) - -/* - * sfe_drv_incr_exceptions() - * increase an exception counter. - */ -static inline void sfe_drv_incr_exceptions(sfe_drv_exception_t except) -{ - struct sfe_drv_ctx_instance_internal *sfe_drv_ctx = &__sfe_drv_ctx; - - spin_lock_bh(&sfe_drv_ctx->lock); - sfe_drv_ctx->exceptions[except]++; - spin_unlock_bh(&sfe_drv_ctx->lock); -} - -/* - * sfe_drv_dev_is_layer_3_interface() - * check if a network device is ipv4 or ipv6 layer 3 interface - * - * @param dev network device to check - * @param check_v4 check ipv4 layer 3 interface(which have ipv4 address) or ipv6 layer 3 interface(which have ipv6 address) - */ -inline bool sfe_drv_dev_is_layer_3_interface(struct net_device *dev, bool check_v4) -{ - struct in_device *in4_dev; - struct inet6_dev *in6_dev; - - BUG_ON(!dev); - - if (likely(check_v4)) { - /* - * Does our input device support IPv4 processing? - */ - in4_dev = (struct in_device *)dev->ip_ptr; - if (unlikely(!in4_dev)) { - return false; - } - - /* - * Does it have an IPv4 address? If it doesn't then we can't do anything - * interesting here! - */ - if (unlikely(!in4_dev->ifa_list)) { - return false; - } - - return true; - } - - /* - * Does our input device support IPv6 processing? - */ - in6_dev = (struct inet6_dev *)dev->ip6_ptr; - if (unlikely(!in6_dev)) { - return false; - } - - /* - * Does it have an IPv6 address? If it doesn't then we can't do anything - * interesting here! - */ - if (unlikely(list_empty(&in6_dev->addr_list))) { - return false; - } - - return true; -} - -/* - * sfe_drv_clean_response_msg_by_type() - * clean response message in queue when ECM exit - * - * @param sfe_drv_ctx sfe driver context - * @param msg_type message type, ipv4 or ipv6 - */ -static void sfe_drv_clean_response_msg_by_type(struct sfe_drv_ctx_instance_internal *sfe_drv_ctx, sfe_drv_msg_types_t msg_type) -{ - struct sfe_drv_response_msg *response, *tmp; - - if (!sfe_drv_ctx) { - return; - } - - spin_lock_bh(&sfe_drv_ctx->lock); - list_for_each_entry_safe(response, tmp, &sfe_drv_ctx->msg_queue, node) { - if (response->type == msg_type) { - list_del(&response->node); - /* - * free response message - */ - kfree(response); - } - } - spin_unlock_bh(&sfe_drv_ctx->lock); - -} - -/* - * sfe_drv_process_response_msg() - * send all pending response message to ECM by calling callback function included in message - * - * @param work work structure - */ -static void sfe_drv_process_response_msg(struct work_struct *work) -{ - struct sfe_drv_ctx_instance_internal *sfe_drv_ctx = container_of(work, struct sfe_drv_ctx_instance_internal, work); - struct sfe_drv_response_msg *response; - - spin_lock_bh(&sfe_drv_ctx->lock); - while ((response = list_first_entry_or_null(&sfe_drv_ctx->msg_queue, struct sfe_drv_response_msg, node))) { - list_del(&response->node); - spin_unlock_bh(&sfe_drv_ctx->lock); - rcu_read_lock(); - - /* - * send response message back to caller - */ - if ((response->type == SFE_DRV_MSG_TYPE_IPV4) && !sfe_drv_ipv4_stopped(sfe_drv_ctx)) { - struct sfe_ipv4_msg *msg = (struct sfe_ipv4_msg *)response->msg; - sfe_ipv4_msg_callback_t callback = (sfe_ipv4_msg_callback_t)msg->cm.cb; - if (callback) { - callback((void *)msg->cm.app_data, msg); - } - } else if ((response->type == SFE_DRV_MSG_TYPE_IPV6) && !sfe_drv_ipv6_stopped(sfe_drv_ctx)) { - struct sfe_ipv6_msg *msg = (struct sfe_ipv6_msg *)response->msg; - sfe_ipv6_msg_callback_t callback = (sfe_ipv6_msg_callback_t)msg->cm.cb; - if (callback) { - callback((void *)msg->cm.app_data, msg); - } - } - - rcu_read_unlock(); - /* - * free response message - */ - kfree(response); - spin_lock_bh(&sfe_drv_ctx->lock); - } - spin_unlock_bh(&sfe_drv_ctx->lock); -} - -/* - * sfe_drv_alloc_response_msg() - * alloc and construct new response message - * - * @param type message type - * @param msg used to construct response message if not NULL - * - * @return !NULL, success; NULL, failed - */ -static struct sfe_drv_response_msg * -sfe_drv_alloc_response_msg(sfe_drv_msg_types_t type, void *msg) -{ - struct sfe_drv_response_msg *response; - int size; - - switch (type) { - case SFE_DRV_MSG_TYPE_IPV4: - size = sizeof(struct sfe_ipv4_msg); - break; - case SFE_DRV_MSG_TYPE_IPV6: - size = sizeof(struct sfe_ipv6_msg); - break; - default: - DEBUG_ERROR("message type %d not supported\n", type); - return NULL; - } - - response = (struct sfe_drv_response_msg *)kzalloc(sizeof(struct sfe_drv_response_msg) + size, GFP_ATOMIC); - if (!response) { - DEBUG_ERROR("allocate memory failed\n"); - return NULL; - } - - response->type = type; - - if (msg) { - memcpy(response->msg, msg, size); - } - - return response; -} - -/* - * sfe_drv_enqueue_msg() - * queue response message - * - * @param sfe_drv_ctx sfe driver context - * @param response response message to be queue - */ -static inline void sfe_drv_enqueue_msg(struct sfe_drv_ctx_instance_internal *sfe_drv_ctx, struct sfe_drv_response_msg *response) -{ - spin_lock_bh(&sfe_drv_ctx->lock); - list_add_tail(&response->node, &sfe_drv_ctx->msg_queue); - spin_unlock_bh(&sfe_drv_ctx->lock); - - schedule_work(&sfe_drv_ctx->work); -} - -/* - * sfe_cmn_msg_init() - * Initialize the common message structure. - * - * @param ncm message to init - * @param if_num interface number related with this message - * @param type message type - * @param cb callback function to process repsonse of this message - * @param app_data argument for above callback function - */ -static void sfe_cmn_msg_init(struct sfe_cmn_msg *ncm, u16 if_num, u32 type, u32 len, void *cb, void *app_data) -{ - ncm->interface = if_num; - ncm->version = SFE_MESSAGE_VERSION; - ncm->type = type; - ncm->len = len; - ncm->cb = (sfe_ptr_t)cb; - ncm->app_data = (sfe_ptr_t)app_data; -} - -/* - * sfe_drv_ipv4_stats_sync_callback() - * Synchronize a connection's state. - * - * @param sis SFE statistics from SFE core engine - */ -static void sfe_drv_ipv4_stats_sync_callback(struct sfe_connection_sync *sis) -{ - struct sfe_drv_ctx_instance_internal *sfe_drv_ctx = &__sfe_drv_ctx; - struct sfe_ipv4_msg msg; - struct sfe_ipv4_conn_sync *sync_msg; - sfe_ipv4_msg_callback_t sync_cb; - - rcu_read_lock(); - sync_cb = rcu_dereference(sfe_drv_ctx->ipv4_stats_sync_cb); - if (!sync_cb) { - rcu_read_unlock(); - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_NO_SYNC_CB); - return; - } - - sync_msg = &msg.msg.conn_stats; - - memset(&msg, 0, sizeof(msg)); - sfe_cmn_msg_init(&msg.cm, 0, SFE_RX_CONN_STATS_SYNC_MSG, - sizeof(struct sfe_ipv4_conn_sync), NULL, NULL); - - /* - * fill connection specific information - */ - sync_msg->protocol = (u8)sis->protocol; - sync_msg->flow_ip = sis->src_ip.ip; - sync_msg->flow_ip_xlate = sis->src_ip_xlate.ip; - sync_msg->flow_ident = sis->src_port; - sync_msg->flow_ident_xlate = sis->src_port_xlate; - - sync_msg->return_ip = sis->dest_ip.ip; - sync_msg->return_ip_xlate = sis->dest_ip_xlate.ip; - sync_msg->return_ident = sis->dest_port; - sync_msg->return_ident_xlate = sis->dest_port_xlate; - - /* - * fill TCP protocol specific information - */ - if (sis->protocol == IPPROTO_TCP) { - sync_msg->flow_max_window = sis->src_td_max_window; - sync_msg->flow_end = sis->src_td_end; - sync_msg->flow_max_end = sis->src_td_max_end; - - sync_msg->return_max_window = sis->dest_td_max_window; - sync_msg->return_end = sis->dest_td_end; - sync_msg->return_max_end = sis->dest_td_max_end; - } - - /* - * fill statistics information - */ - sync_msg->flow_rx_packet_count = sis->src_new_packet_count; - sync_msg->flow_rx_byte_count = sis->src_new_byte_count; - sync_msg->flow_tx_packet_count = sis->dest_new_packet_count; - sync_msg->flow_tx_byte_count = sis->dest_new_byte_count; - - sync_msg->return_rx_packet_count = sis->dest_new_packet_count; - sync_msg->return_rx_byte_count = sis->dest_new_byte_count; - sync_msg->return_tx_packet_count = sis->src_new_packet_count; - sync_msg->return_tx_byte_count = sis->src_new_byte_count; - - /* - * fill expiration time to extend, in unit of msec - */ - sync_msg->inc_ticks = (((u32)sis->delta_jiffies) * MSEC_PER_SEC)/HZ; - - /* - * fill other information - */ - switch (sis->reason) { - case SFE_SYNC_REASON_DESTROY: - sync_msg->reason = SFE_RULE_SYNC_REASON_DESTROY; - break; - case SFE_SYNC_REASON_FLUSH: - sync_msg->reason = SFE_RULE_SYNC_REASON_FLUSH; - break; - default: - sync_msg->reason = SFE_RULE_SYNC_REASON_STATS; - break; - } - - /* - * SFE sync calling is excuted in a timer, so we can redirect it to ECM directly. - */ - sync_cb(sfe_drv_ctx->ipv4_stats_sync_data, &msg); - rcu_read_unlock(); -} - -/* - * sfe_drv_create_ipv4_rule_msg() - * convert create message format from ecm to sfe - * - * @param sfe_drv_ctx sfe driver context - * @param msg The IPv4 message - * - * @return sfe_tx_status_t The status of the Tx operation - */ -sfe_tx_status_t sfe_drv_create_ipv4_rule_msg(struct sfe_drv_ctx_instance_internal *sfe_drv_ctx, struct sfe_ipv4_msg *msg) -{ - struct sfe_connection_create sic; - struct net_device *src_dev = NULL; - struct net_device *dest_dev = NULL; - struct sfe_drv_response_msg *response; - enum sfe_cmn_response ret; - - response = sfe_drv_alloc_response_msg(SFE_DRV_MSG_TYPE_IPV4, msg); - if (!response) { - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_ENQUEUE_FAILED); - return SFE_TX_FAILURE_QUEUE; - } - - if (!(msg->msg.rule_create.valid_flags & SFE_RULE_CREATE_CONN_VALID)) { - ret = SFE_CMN_RESPONSE_EMSG; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_CONNECTION_INVALID); - goto failed_ret; - } - - /* - * not support bridged flows now - */ - if (msg->msg.rule_create.rule_flags & SFE_RULE_CREATE_FLAG_BRIDGE_FLOW) { - ret = SFE_CMN_RESPONSE_EINTERFACE; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_NOT_SUPPORT_BRIDGE); - goto failed_ret; - } - - sic.protocol = msg->msg.rule_create.tuple.protocol; - sic.src_ip.ip = msg->msg.rule_create.tuple.flow_ip; - sic.dest_ip.ip = msg->msg.rule_create.tuple.return_ip; - sic.src_ip_xlate.ip = msg->msg.rule_create.conn_rule.flow_ip_xlate; - sic.dest_ip_xlate.ip = msg->msg.rule_create.conn_rule.return_ip_xlate; - - sic.flags = 0; - switch (sic.protocol) { - case IPPROTO_TCP: - if (!(msg->msg.rule_create.valid_flags & SFE_RULE_CREATE_TCP_VALID)) { - ret = SFE_CMN_RESPONSE_EMSG; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_TCP_INVALID); - goto failed_ret; - } - - sic.src_port = msg->msg.rule_create.tuple.flow_ident; - sic.dest_port = msg->msg.rule_create.tuple.return_ident; - sic.src_port_xlate = msg->msg.rule_create.conn_rule.flow_ident_xlate; - sic.dest_port_xlate = msg->msg.rule_create.conn_rule.return_ident_xlate; - sic.src_td_window_scale = msg->msg.rule_create.tcp_rule.flow_window_scale; - sic.src_td_max_window = msg->msg.rule_create.tcp_rule.flow_max_window; - sic.src_td_end = msg->msg.rule_create.tcp_rule.flow_end; - sic.src_td_max_end = msg->msg.rule_create.tcp_rule.flow_max_end; - sic.dest_td_window_scale = msg->msg.rule_create.tcp_rule.return_window_scale; - sic.dest_td_max_window = msg->msg.rule_create.tcp_rule.return_max_window; - sic.dest_td_end = msg->msg.rule_create.tcp_rule.return_end; - sic.dest_td_max_end = msg->msg.rule_create.tcp_rule.return_max_end; - if (msg->msg.rule_create.rule_flags & SFE_RULE_CREATE_FLAG_NO_SEQ_CHECK) { - sic.flags |= SFE_CREATE_FLAG_NO_SEQ_CHECK; - } - break; - - case IPPROTO_UDP: - sic.src_port = msg->msg.rule_create.tuple.flow_ident; - sic.dest_port = msg->msg.rule_create.tuple.return_ident; - sic.src_port_xlate = msg->msg.rule_create.conn_rule.flow_ident_xlate; - sic.dest_port_xlate = msg->msg.rule_create.conn_rule.return_ident_xlate; - break; - - default: - ret = SFE_CMN_RESPONSE_EMSG; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_PROTOCOL_NOT_SUPPORT); - goto failed_ret; - } - - memcpy(sic.src_mac, msg->msg.rule_create.conn_rule.flow_mac, ETH_ALEN); - memset(sic.src_mac_xlate, 0, ETH_ALEN); - memset(sic.dest_mac, 0, ETH_ALEN); - memcpy(sic.dest_mac_xlate, msg->msg.rule_create.conn_rule.return_mac, ETH_ALEN); - - /* - * Does our input device support IP processing? - */ - src_dev = dev_get_by_index(&init_net, msg->msg.rule_create.conn_rule.flow_top_interface_num); - if (!src_dev || !sfe_drv_dev_is_layer_3_interface(src_dev, true)) { - ret = SFE_CMN_RESPONSE_EINTERFACE; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_SRC_DEV_NOT_L3); - goto failed_ret; - } - - /* - * Does our output device support IP processing? - */ - dest_dev = dev_get_by_index(&init_net, msg->msg.rule_create.conn_rule.return_top_interface_num); - if (!dest_dev || !sfe_drv_dev_is_layer_3_interface(dest_dev, true)) { - ret = SFE_CMN_RESPONSE_EINTERFACE; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_DEST_DEV_NOT_L3); - goto failed_ret; - } - - sic.src_dev = src_dev; - sic.dest_dev = dest_dev; - - sic.src_mtu = msg->msg.rule_create.conn_rule.flow_mtu; - sic.dest_mtu = msg->msg.rule_create.conn_rule.return_mtu; - - if (msg->msg.rule_create.valid_flags & SFE_RULE_CREATE_QOS_VALID) { - sic.src_priority = msg->msg.rule_create.qos_rule.flow_qos_tag; - sic.dest_priority = msg->msg.rule_create.qos_rule.return_qos_tag; - sic.flags |= SFE_CREATE_FLAG_REMARK_PRIORITY; - } - - if (msg->msg.rule_create.valid_flags & SFE_RULE_CREATE_DSCP_MARKING_VALID) { - sic.src_dscp = msg->msg.rule_create.dscp_rule.flow_dscp; - sic.dest_dscp = msg->msg.rule_create.dscp_rule.return_dscp; - sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; - } - -#ifdef CONFIG_XFRM - if (msg->msg.rule_create.valid_flags & SFE_RULE_CREATE_DIRECTION_VALID) { - sic.original_accel = msg->msg.rule_create.direction_rule.flow_accel; - sic.reply_accel = msg->msg.rule_create.direction_rule.return_accel; - } else { - sic.original_accel = sic.reply_accel = 1; - } -#endif - - if (!sfe_ipv4_create_rule(&sic)) { - /* success */ - ret = SFE_CMN_RESPONSE_ACK; - } else { - /* failed */ - ret = SFE_CMN_RESPONSE_EMSG; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_CREATE_FAILED); - } - - /* - * fall through - */ -failed_ret: - if (src_dev) { - dev_put(src_dev); - } - - if (dest_dev) { - dev_put(dest_dev); - } - - /* - * try to queue response message - */ - ((struct sfe_ipv4_msg *)response->msg)->cm.response = msg->cm.response = ret; - sfe_drv_enqueue_msg(sfe_drv_ctx, response); - - return SFE_TX_SUCCESS; -} - -/* - * sfe_drv_destroy_ipv4_rule_msg() - * convert destroy message format from ecm to sfe - * - * @param sfe_drv_ctx sfe driver context - * @param msg The IPv4 message - * - * @return sfe_tx_status_t The status of the Tx operation - */ -sfe_tx_status_t sfe_drv_destroy_ipv4_rule_msg(struct sfe_drv_ctx_instance_internal *sfe_drv_ctx, struct sfe_ipv4_msg *msg) -{ - struct sfe_connection_destroy sid; - struct sfe_drv_response_msg *response; - - response = sfe_drv_alloc_response_msg(SFE_DRV_MSG_TYPE_IPV4, msg); - if (!response) { - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_ENQUEUE_FAILED); - return SFE_TX_FAILURE_QUEUE; - } - - sid.protocol = msg->msg.rule_destroy.tuple.protocol; - sid.src_ip.ip = msg->msg.rule_destroy.tuple.flow_ip; - sid.dest_ip.ip = msg->msg.rule_destroy.tuple.return_ip; - sid.src_port = msg->msg.rule_destroy.tuple.flow_ident; - sid.dest_port = msg->msg.rule_destroy.tuple.return_ident; - - sfe_ipv4_destroy_rule(&sid); - - /* - * try to queue response message - */ - ((struct sfe_ipv4_msg *)response->msg)->cm.response = msg->cm.response = SFE_CMN_RESPONSE_ACK; - sfe_drv_enqueue_msg(sfe_drv_ctx, response); - - return SFE_TX_SUCCESS; -} - -/* - * sfe_drv_ipv4_tx() - * Transmit an IPv4 message to the sfe - * - * @param sfe_drv_ctx sfe driver context - * @param msg The IPv4 message - * - * @return sfe_tx_status_t The status of the Tx operation - */ -sfe_tx_status_t sfe_drv_ipv4_tx(struct sfe_drv_ctx_instance *sfe_drv_ctx, struct sfe_ipv4_msg *msg) -{ - switch (msg->cm.type) { - case SFE_TX_CREATE_RULE_MSG: - return sfe_drv_create_ipv4_rule_msg(SFE_DRV_CTX_TO_PRIVATE(sfe_drv_ctx), msg); - case SFE_TX_DESTROY_RULE_MSG: - return sfe_drv_destroy_ipv4_rule_msg(SFE_DRV_CTX_TO_PRIVATE(sfe_drv_ctx), msg); - default: - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_IPV4_MSG_UNKNOW); - return SFE_TX_FAILURE_NOT_ENABLED; - } -} -EXPORT_SYMBOL(sfe_drv_ipv4_tx); - -/* - * sfe_ipv4_msg_init() - * Initialize IPv4 message. - */ -void sfe_ipv4_msg_init(struct sfe_ipv4_msg *nim, u16 if_num, u32 type, u32 len, - sfe_ipv4_msg_callback_t cb, void *app_data) -{ - sfe_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data); -} -EXPORT_SYMBOL(sfe_ipv4_msg_init); - -/* - * sfe_drv_ipv4_max_conn_count() - * return maximum number of entries SFE supported - */ -int sfe_drv_ipv4_max_conn_count(void) -{ - return SFE_MAX_CONNECTION_NUM; -} -EXPORT_SYMBOL(sfe_drv_ipv4_max_conn_count); - -/* - * sfe_drv_ipv4_notify_register() - * Register a notifier callback for IPv4 messages from sfe driver - * - * @param cb The callback pointer - * @param app_data The application context for this message - * - * @return struct sfe_drv_ctx_instance * The sfe driver context - */ -struct sfe_drv_ctx_instance *sfe_drv_ipv4_notify_register(sfe_ipv4_msg_callback_t cb, void *app_data) -{ - struct sfe_drv_ctx_instance_internal *sfe_drv_ctx = &__sfe_drv_ctx; - - spin_lock_bh(&sfe_drv_ctx->lock); - /* - * Hook the shortcut sync callback. - */ - if (cb && !sfe_drv_ctx->ipv4_stats_sync_cb) { - sfe_ipv4_register_sync_rule_callback(sfe_drv_ipv4_stats_sync_callback); - } - - rcu_assign_pointer(sfe_drv_ctx->ipv4_stats_sync_cb, cb); - sfe_drv_ctx->ipv4_stats_sync_data = app_data; - - spin_unlock_bh(&sfe_drv_ctx->lock); - - return SFE_DRV_CTX_TO_PUBLIC(sfe_drv_ctx); -} -EXPORT_SYMBOL(sfe_drv_ipv4_notify_register); - -/* - * sfe_drv_ipv4_notify_unregister() - * Un-Register a notifier callback for IPv4 messages from sfe driver - */ -void sfe_drv_ipv4_notify_unregister(void) -{ - struct sfe_drv_ctx_instance_internal *sfe_drv_ctx = &__sfe_drv_ctx; - - spin_lock_bh(&sfe_drv_ctx->lock); - /* - * Unregister our sync callback. - */ - if (sfe_drv_ctx->ipv4_stats_sync_cb) { - sfe_ipv4_register_sync_rule_callback(NULL); - rcu_assign_pointer(sfe_drv_ctx->ipv4_stats_sync_cb, NULL); - sfe_drv_ctx->ipv4_stats_sync_data = NULL; - } - spin_unlock_bh(&sfe_drv_ctx->lock); - - sfe_drv_clean_response_msg_by_type(sfe_drv_ctx, SFE_DRV_MSG_TYPE_IPV4); - - return; -} -EXPORT_SYMBOL(sfe_drv_ipv4_notify_unregister); - -/* - * sfe_drv_ipv6_stats_sync_callback() - * Synchronize a connection's state. - */ -static void sfe_drv_ipv6_stats_sync_callback(struct sfe_connection_sync *sis) -{ - struct sfe_drv_ctx_instance_internal *sfe_drv_ctx = &__sfe_drv_ctx; - struct sfe_ipv6_msg msg; - struct sfe_ipv6_conn_sync *sync_msg; - sfe_ipv6_msg_callback_t sync_cb; - - rcu_read_lock(); - sync_cb = rcu_dereference(sfe_drv_ctx->ipv6_stats_sync_cb); - if (!sync_cb) { - rcu_read_unlock(); - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_NO_SYNC_CB); - return; - } - - sync_msg = &msg.msg.conn_stats; - - memset(&msg, 0, sizeof(msg)); - sfe_cmn_msg_init(&msg.cm, 0, SFE_RX_CONN_STATS_SYNC_MSG, - sizeof(struct sfe_ipv6_conn_sync), NULL, NULL); - - /* - * fill connection specific information - */ - sync_msg->protocol = (u8)sis->protocol; - sfe_drv_ipv6_addr_copy(sis->src_ip.ip6, sync_msg->flow_ip); - sync_msg->flow_ident = sis->src_port; - - sfe_drv_ipv6_addr_copy(sis->dest_ip.ip6, sync_msg->return_ip); - sync_msg->return_ident = sis->dest_port; - - /* - * fill TCP protocol specific information - */ - if (sis->protocol == IPPROTO_TCP) { - sync_msg->flow_max_window = sis->src_td_max_window; - sync_msg->flow_end = sis->src_td_end; - sync_msg->flow_max_end = sis->src_td_max_end; - - sync_msg->return_max_window = sis->dest_td_max_window; - sync_msg->return_end = sis->dest_td_end; - sync_msg->return_max_end = sis->dest_td_max_end; - } - - /* - * fill statistics information - */ - sync_msg->flow_rx_packet_count = sis->src_new_packet_count; - sync_msg->flow_rx_byte_count = sis->src_new_byte_count; - sync_msg->flow_tx_packet_count = sis->dest_new_packet_count; - sync_msg->flow_tx_byte_count = sis->dest_new_byte_count; - - sync_msg->return_rx_packet_count = sis->dest_new_packet_count; - sync_msg->return_rx_byte_count = sis->dest_new_byte_count; - sync_msg->return_tx_packet_count = sis->src_new_packet_count; - sync_msg->return_tx_byte_count = sis->src_new_byte_count; - - /* - * fill expiration time to extend, in unit of msec - */ - sync_msg->inc_ticks = (((u32)sis->delta_jiffies) * MSEC_PER_SEC)/HZ; - - /* - * fill other information - */ - switch (sis->reason) { - case SFE_SYNC_REASON_DESTROY: - sync_msg->reason = SFE_RULE_SYNC_REASON_DESTROY; - break; - case SFE_SYNC_REASON_FLUSH: - sync_msg->reason = SFE_RULE_SYNC_REASON_FLUSH; - break; - default: - sync_msg->reason = SFE_RULE_SYNC_REASON_STATS; - break; - } - - /* - * SFE sync calling is excuted in a timer, so we can redirect it to ECM directly. - */ - sync_cb(sfe_drv_ctx->ipv6_stats_sync_data, &msg); - rcu_read_unlock(); -} - -/* - * sfe_drv_create_ipv6_rule_msg() - * convert create message format from ecm to sfe - * - * @param sfe_drv_ctx sfe driver context - * @param msg The IPv6 message - * - * @return sfe_tx_status_t The status of the Tx operation - */ -sfe_tx_status_t sfe_drv_create_ipv6_rule_msg(struct sfe_drv_ctx_instance_internal *sfe_drv_ctx, struct sfe_ipv6_msg *msg) -{ - struct sfe_connection_create sic; - struct net_device *src_dev = NULL; - struct net_device *dest_dev = NULL; - struct sfe_drv_response_msg *response; - enum sfe_cmn_response ret; - - response = sfe_drv_alloc_response_msg(SFE_DRV_MSG_TYPE_IPV6, msg); - if (!response) { - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_ENQUEUE_FAILED); - return SFE_TX_FAILURE_QUEUE; - } - - if (!(msg->msg.rule_create.valid_flags & SFE_RULE_CREATE_CONN_VALID)) { - ret = SFE_CMN_RESPONSE_EMSG; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_CONNECTION_INVALID); - goto failed_ret; - } - - /* - * not support bridged flows now - */ - if (msg->msg.rule_create.rule_flags & SFE_RULE_CREATE_FLAG_BRIDGE_FLOW) { - ret = SFE_CMN_RESPONSE_EINTERFACE; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_NOT_SUPPORT_BRIDGE); - goto failed_ret; - } - - sic.protocol = msg->msg.rule_create.tuple.protocol; - sfe_drv_ipv6_addr_copy(msg->msg.rule_create.tuple.flow_ip, sic.src_ip.ip6); - sfe_drv_ipv6_addr_copy(msg->msg.rule_create.tuple.return_ip, sic.dest_ip.ip6); - sfe_drv_ipv6_addr_copy(msg->msg.rule_create.tuple.flow_ip, sic.src_ip_xlate.ip6); - sfe_drv_ipv6_addr_copy(msg->msg.rule_create.tuple.return_ip, sic.dest_ip_xlate.ip6); - - sic.flags = 0; - switch (sic.protocol) { - case IPPROTO_TCP: - if (!(msg->msg.rule_create.valid_flags & SFE_RULE_CREATE_TCP_VALID)) { - ret = SFE_CMN_RESPONSE_EMSG; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_TCP_INVALID); - goto failed_ret; - } - - sic.src_port = msg->msg.rule_create.tuple.flow_ident; - sic.dest_port = msg->msg.rule_create.tuple.return_ident; - sic.src_port_xlate = msg->msg.rule_create.tuple.flow_ident; - sic.dest_port_xlate = msg->msg.rule_create.tuple.return_ident; - sic.src_td_window_scale = msg->msg.rule_create.tcp_rule.flow_window_scale; - sic.src_td_max_window = msg->msg.rule_create.tcp_rule.flow_max_window; - sic.src_td_end = msg->msg.rule_create.tcp_rule.flow_end; - sic.src_td_max_end = msg->msg.rule_create.tcp_rule.flow_max_end; - sic.dest_td_window_scale = msg->msg.rule_create.tcp_rule.return_window_scale; - sic.dest_td_max_window = msg->msg.rule_create.tcp_rule.return_max_window; - sic.dest_td_end = msg->msg.rule_create.tcp_rule.return_end; - sic.dest_td_max_end = msg->msg.rule_create.tcp_rule.return_max_end; - if (msg->msg.rule_create.rule_flags & SFE_RULE_CREATE_FLAG_NO_SEQ_CHECK) { - sic.flags |= SFE_CREATE_FLAG_NO_SEQ_CHECK; - } - break; - - case IPPROTO_UDP: - sic.src_port = msg->msg.rule_create.tuple.flow_ident; - sic.dest_port = msg->msg.rule_create.tuple.return_ident; - sic.src_port_xlate = msg->msg.rule_create.tuple.flow_ident; - sic.dest_port_xlate = msg->msg.rule_create.tuple.return_ident; - break; - - default: - ret = SFE_CMN_RESPONSE_EMSG; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_PROTOCOL_NOT_SUPPORT); - goto failed_ret; - } - - memcpy(sic.src_mac, msg->msg.rule_create.conn_rule.flow_mac, ETH_ALEN); - memset(sic.src_mac_xlate, 0, ETH_ALEN); - memset(sic.dest_mac, 0, ETH_ALEN); - memcpy(sic.dest_mac_xlate, msg->msg.rule_create.conn_rule.return_mac, ETH_ALEN); - /* - * Does our input device support IP processing? - */ - src_dev = dev_get_by_index(&init_net, msg->msg.rule_create.conn_rule.flow_top_interface_num); - if (!src_dev || !sfe_drv_dev_is_layer_3_interface(src_dev, false)) { - ret = SFE_CMN_RESPONSE_EINTERFACE; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_SRC_DEV_NOT_L3); - goto failed_ret; - } - - /* - * Does our output device support IP processing? - */ - dest_dev = dev_get_by_index(&init_net, msg->msg.rule_create.conn_rule.return_top_interface_num); - if (!dest_dev || !sfe_drv_dev_is_layer_3_interface(dest_dev, false)) { - ret = SFE_CMN_RESPONSE_EINTERFACE; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_DEST_DEV_NOT_L3); - goto failed_ret; - } - - sic.src_dev = src_dev; - sic.dest_dev = dest_dev; - - sic.src_mtu = msg->msg.rule_create.conn_rule.flow_mtu; - sic.dest_mtu = msg->msg.rule_create.conn_rule.return_mtu; - - if (msg->msg.rule_create.valid_flags & SFE_RULE_CREATE_QOS_VALID) { - sic.src_priority = msg->msg.rule_create.qos_rule.flow_qos_tag; - sic.dest_priority = msg->msg.rule_create.qos_rule.return_qos_tag; - sic.flags |= SFE_CREATE_FLAG_REMARK_PRIORITY; - } - - if (msg->msg.rule_create.valid_flags & SFE_RULE_CREATE_DSCP_MARKING_VALID) { - sic.src_dscp = msg->msg.rule_create.dscp_rule.flow_dscp; - sic.dest_dscp = msg->msg.rule_create.dscp_rule.return_dscp; - sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; - } - -#ifdef CONFIG_XFRM - if (msg->msg.rule_create.valid_flags & SFE_RULE_CREATE_DIRECTION_VALID) { - sic.original_accel = msg->msg.rule_create.direction_rule.flow_accel; - sic.reply_accel = msg->msg.rule_create.direction_rule.return_accel; - } else { - sic.original_accel = sic.reply_accel = 1; - } -#endif - - if (!sfe_ipv6_create_rule(&sic)) { - /* success */ - ret = SFE_CMN_RESPONSE_ACK; - } else { - /* failed */ - ret = SFE_CMN_RESPONSE_EMSG; - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_CREATE_FAILED); - } - - /* - * fall through - */ -failed_ret: - if (src_dev) { - dev_put(src_dev); - } - - if (dest_dev) { - dev_put(dest_dev); - } - - /* - * try to queue response message - */ - ((struct sfe_ipv6_msg *)response->msg)->cm.response = msg->cm.response = ret; - sfe_drv_enqueue_msg(sfe_drv_ctx, response); - - return SFE_TX_SUCCESS; -} - -/* - * sfe_drv_destroy_ipv6_rule_msg() - * convert destroy message format from ecm to sfe - * - * @param sfe_drv_ctx sfe driver context - * @param msg The IPv6 message - * - * @return sfe_tx_status_t The status of the Tx operation - */ -sfe_tx_status_t sfe_drv_destroy_ipv6_rule_msg(struct sfe_drv_ctx_instance_internal *sfe_drv_ctx, struct sfe_ipv6_msg *msg) -{ - struct sfe_connection_destroy sid; - struct sfe_drv_response_msg *response; - - response = sfe_drv_alloc_response_msg(SFE_DRV_MSG_TYPE_IPV6, msg); - if (!response) { - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_ENQUEUE_FAILED); - return SFE_TX_FAILURE_QUEUE; - } - - sid.protocol = msg->msg.rule_destroy.tuple.protocol; - sfe_drv_ipv6_addr_copy(msg->msg.rule_destroy.tuple.flow_ip, sid.src_ip.ip6); - sfe_drv_ipv6_addr_copy(msg->msg.rule_destroy.tuple.return_ip, sid.dest_ip.ip6); - sid.src_port = msg->msg.rule_destroy.tuple.flow_ident; - sid.dest_port = msg->msg.rule_destroy.tuple.return_ident; - - sfe_ipv6_destroy_rule(&sid); - - /* - * try to queue response message - */ - ((struct sfe_ipv6_msg *)response->msg)->cm.response = msg->cm.response = SFE_CMN_RESPONSE_ACK; - sfe_drv_enqueue_msg(sfe_drv_ctx, response); - - return SFE_TX_SUCCESS; -} - -/* - * sfe_drv_ipv6_tx() - * Transmit an IPv6 message to the sfe - * - * @param sfe_drv_ctx sfe driver context - * @param msg The IPv6 message - * - * @return sfe_tx_status_t The status of the Tx operation - */ -sfe_tx_status_t sfe_drv_ipv6_tx(struct sfe_drv_ctx_instance *sfe_drv_ctx, struct sfe_ipv6_msg *msg) -{ - switch (msg->cm.type) { - case SFE_TX_CREATE_RULE_MSG: - return sfe_drv_create_ipv6_rule_msg(SFE_DRV_CTX_TO_PRIVATE(sfe_drv_ctx), msg); - case SFE_TX_DESTROY_RULE_MSG: - return sfe_drv_destroy_ipv6_rule_msg(SFE_DRV_CTX_TO_PRIVATE(sfe_drv_ctx), msg); - default: - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_IPV6_MSG_UNKNOW); - return SFE_TX_FAILURE_NOT_ENABLED; - } -} -EXPORT_SYMBOL(sfe_drv_ipv6_tx); - -/* - * sfe_ipv6_msg_init() - * Initialize IPv6 message. - */ -void sfe_ipv6_msg_init(struct sfe_ipv6_msg *nim, u16 if_num, u32 type, u32 len, - sfe_ipv6_msg_callback_t cb, void *app_data) -{ - sfe_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data); -} -EXPORT_SYMBOL(sfe_ipv6_msg_init); - -/* - * sfe_drv_ipv6_max_conn_count() - * return maximum number of entries SFE supported - */ -int sfe_drv_ipv6_max_conn_count(void) -{ - return SFE_MAX_CONNECTION_NUM; -} -EXPORT_SYMBOL(sfe_drv_ipv6_max_conn_count); - -/* - * sfe_drv_ipv6_notify_register() - * Register a notifier callback for IPv6 messages from sfe driver - * - * @param cb The callback pointer - * @param app_data The application context for this message - * - * @return struct sfe_drv_ctx_instance * The sfe driver context - */ -struct sfe_drv_ctx_instance *sfe_drv_ipv6_notify_register(sfe_ipv6_msg_callback_t cb, void *app_data) -{ - struct sfe_drv_ctx_instance_internal *sfe_drv_ctx = &__sfe_drv_ctx; - - spin_lock_bh(&sfe_drv_ctx->lock); - /* - * Hook the shortcut sync callback. - */ - if (cb && !sfe_drv_ctx->ipv6_stats_sync_cb) { - sfe_ipv6_register_sync_rule_callback(sfe_drv_ipv6_stats_sync_callback); - } - - rcu_assign_pointer(sfe_drv_ctx->ipv6_stats_sync_cb, cb); - sfe_drv_ctx->ipv6_stats_sync_data = app_data; - - spin_unlock_bh(&sfe_drv_ctx->lock); - - return SFE_DRV_CTX_TO_PUBLIC(sfe_drv_ctx); -} -EXPORT_SYMBOL(sfe_drv_ipv6_notify_register); - -/* - * sfe_drv_ipv6_notify_unregister() - * Un-Register a notifier callback for IPv6 messages from sfe driver - */ -void sfe_drv_ipv6_notify_unregister(void) -{ - struct sfe_drv_ctx_instance_internal *sfe_drv_ctx = &__sfe_drv_ctx; - - spin_lock_bh(&sfe_drv_ctx->lock); - /* - * Unregister our sync callback. - */ - if (sfe_drv_ctx->ipv6_stats_sync_cb) { - sfe_ipv6_register_sync_rule_callback(NULL); - rcu_assign_pointer(sfe_drv_ctx->ipv6_stats_sync_cb, NULL); - sfe_drv_ctx->ipv6_stats_sync_data = NULL; - } - spin_unlock_bh(&sfe_drv_ctx->lock); - - sfe_drv_clean_response_msg_by_type(sfe_drv_ctx, SFE_DRV_MSG_TYPE_IPV6); - - return; -} -EXPORT_SYMBOL(sfe_drv_ipv6_notify_unregister); - -/* - * sfe_tun6rd_tx() - * Transmit a tun6rd message to sfe engine - */ -sfe_tx_status_t sfe_tun6rd_tx(struct sfe_drv_ctx_instance *sfe_drv_ctx, struct sfe_tun6rd_msg *msg) -{ - sfe_drv_incr_exceptions(SFE_DRV_EXCEPTION_NOT_SUPPORT_6RD); - return SFE_TX_FAILURE_NOT_ENABLED; -} -EXPORT_SYMBOL(sfe_tun6rd_tx); - -/* - * sfe_tun6rd_msg_init() - * Initialize sfe_tun6rd msg. - */ -void sfe_tun6rd_msg_init(struct sfe_tun6rd_msg *ncm, u16 if_num, u32 type, u32 len, void *cb, void *app_data) -{ - sfe_cmn_msg_init(&ncm->cm, if_num, type, len, cb, app_data); -} -EXPORT_SYMBOL(sfe_tun6rd_msg_init); - -/* - * sfe_drv_recv() - * Handle packet receives. - * - * Returns 1 if the packet is forwarded or 0 if it isn't. - */ -int sfe_drv_recv(struct sk_buff *skb) -{ - struct net_device *dev; - - /* - * We know that for the vast majority of packets we need the transport - * layer header so we may as well start to fetch it now! - */ - prefetch(skb->data + 32); - barrier(); - - dev = skb->dev; - -/* - * TODO: Remove the check when INgress Qdisc is ported to 5.4 kernel. - */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) -#ifdef CONFIG_NET_CLS_ACT - /* - * If ingress Qdisc configured, and packet not processed by ingress Qdisc yet - * We can not accelerate this packet. - */ - if (dev->ingress_queue && !(skb->tc_verd & TC_NCLS)) { - return 0; - } -#endif -#endif - - /* - * We're only interested in IPv4 and IPv6 packets. - */ - if (likely(htons(ETH_P_IP) == skb->protocol)) { - if (sfe_drv_dev_is_layer_3_interface(dev, true)) { - return sfe_ipv4_recv(dev, skb); - } else { - DEBUG_TRACE("no IPv4 address for device: %s\n", dev->name); - return 0; - } - } - - if (likely(htons(ETH_P_IPV6) == skb->protocol)) { - if (sfe_drv_dev_is_layer_3_interface(dev, false)) { - return sfe_ipv6_recv(dev, skb); - } else { - DEBUG_TRACE("no IPv6 address for device: %s\n", dev->name); - return 0; - } - } - - DEBUG_TRACE("not IP packet\n"); - return 0; -} - -/* - * sfe_drv_get_exceptions() - * dump exception counters - */ -static ssize_t sfe_drv_get_exceptions(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int idx, len; - struct sfe_drv_ctx_instance_internal *sfe_drv_ctx = &__sfe_drv_ctx; - - spin_lock_bh(&sfe_drv_ctx->lock); - for (len = 0, idx = 0; idx < SFE_DRV_EXCEPTION_MAX; idx++) { - if (sfe_drv_ctx->exceptions[idx]) { - len += snprintf(buf + len, (ssize_t)(PAGE_SIZE - len), "%s = %d\n", sfe_drv_exception_events_string[idx], sfe_drv_ctx->exceptions[idx]); - } - } - spin_unlock_bh(&sfe_drv_ctx->lock); - - return len; -} - -/* - * sysfs attributes. - */ -static const struct device_attribute sfe_drv_exceptions_attr = - __ATTR(exceptions, S_IRUGO, sfe_drv_get_exceptions, NULL); - -/* - * sfe_drv_init() - */ -static int __init sfe_drv_init(void) -{ - struct sfe_drv_ctx_instance_internal *sfe_drv_ctx = &__sfe_drv_ctx; - int result = -1; - - /* - * Create sys/sfe_drv - */ - sfe_drv_ctx->sys_sfe_drv = kobject_create_and_add("sfe_drv", NULL); - if (!sfe_drv_ctx->sys_sfe_drv) { - DEBUG_ERROR("failed to register sfe_drv\n"); - goto exit1; - } - - /* - * Create sys/sfe_drv/exceptions - */ - result = sysfs_create_file(sfe_drv_ctx->sys_sfe_drv, &sfe_drv_exceptions_attr.attr); - if (result) { - DEBUG_ERROR("failed to register exceptions file: %d\n", result); - goto exit2; - } - - spin_lock_init(&sfe_drv_ctx->lock); - - INIT_LIST_HEAD(&sfe_drv_ctx->msg_queue); - INIT_WORK(&sfe_drv_ctx->work, sfe_drv_process_response_msg); - - /* - * Hook the receive path in the network stack. - */ - BUG_ON(athrs_fast_nat_recv); - RCU_INIT_POINTER(athrs_fast_nat_recv, sfe_drv_recv); - - return 0; -exit2: - kobject_put(sfe_drv_ctx->sys_sfe_drv); -exit1: - return result; -} - -/* - * sfe_drv_exit() - */ -static void __exit sfe_drv_exit(void) -{ - struct sfe_drv_ctx_instance_internal *sfe_drv_ctx = &__sfe_drv_ctx; - - /* - * Unregister our receive callback. - */ - RCU_INIT_POINTER(athrs_fast_nat_recv, NULL); - - /* - * Wait for all callbacks to complete. - */ - rcu_barrier(); - - /* - * Destroy all connections. - */ - sfe_ipv4_destroy_all_rules_for_dev(NULL); - sfe_ipv6_destroy_all_rules_for_dev(NULL); - - /* - * stop work queue, and flush all pending message in queue - */ - cancel_work_sync(&sfe_drv_ctx->work); - sfe_drv_process_response_msg(&sfe_drv_ctx->work); - - /* - * Unregister our sync callback. - */ - sfe_drv_ipv4_notify_unregister(); - sfe_drv_ipv6_notify_unregister(); - - kobject_put(sfe_drv_ctx->sys_sfe_drv); - - return; -} - -module_init(sfe_drv_init) -module_exit(sfe_drv_exit) - -MODULE_AUTHOR("Qualcomm Atheros Inc."); -MODULE_DESCRIPTION("Simulated driver for Shortcut Forwarding Engine"); -MODULE_LICENSE("Dual BSD/GPL"); - diff --git a/simulated-driver/sfe_drv.h b/simulated-driver/sfe_drv.h deleted file mode 100644 index 729caffd3..000000000 --- a/simulated-driver/sfe_drv.h +++ /dev/null @@ -1,553 +0,0 @@ -/* - * sfe_drv.h - * simulated driver headers for shortcut forwarding engine. - * - * Copyright (c) 2015,2016 The Linux Foundation. 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. - */ - -#ifndef __SFE_DRV_H -#define __SFE_DRV_H - -#define MAX_VLAN_DEPTH 2 -#define SFE_VLAN_ID_NOT_CONFIGURED 0xfff -#define SFE_MC_IF_MAX 16 - -#define SFE_SPECIAL_INTERFACE_BASE 0x7f00 -#define SFE_SPECIAL_INTERFACE_IPV4 (SFE_SPECIAL_INTERFACE_BASE + 1) -#define SFE_SPECIAL_INTERFACE_IPV6 (SFE_SPECIAL_INTERFACE_BASE + 2) -#define SFE_SPECIAL_INTERFACE_IPSEC (SFE_SPECIAL_INTERFACE_BASE + 3) -#define SFE_SPECIAL_INTERFACE_L2TP (SFE_SPECIAL_INTERFACE_BASE + 4) -#define SFE_SPECIAL_INTERFACE_PPTP (SFE_SPECIAL_INTERFACE_BASE + 5) - -/** - * Rule creation & rule update flags. - */ -#define SFE_RULE_CREATE_FLAG_NO_SEQ_CHECK (1<<0) /**< Do not perform TCP sequence number checks */ -#define SFE_RULE_CREATE_FLAG_BRIDGE_FLOW (1<<1) /**< This is a pure bridge forwarding flow */ -#define SFE_RULE_CREATE_FLAG_ROUTED (1<<2) /**< Rule is for a routed connection */ -#define SFE_RULE_CREATE_FLAG_DSCP_MARKING (1<<3) /**< Rule has for a DSCP marking configured*/ -#define SFE_RULE_CREATE_FLAG_VLAN_MARKING (1<<4) /**< Rule has for a VLAN marking configured*/ -#define SFE_RULE_UPDATE_FLAG_CHANGE_MTU (1<<5) /**< Update MTU of connection interfaces */ -#define SFE_RULE_CREATE_FLAG_ICMP_NO_CME_FLUSH (1<<6)/**< Rule for not flushing CME on ICMP pkt */ -#define SFE_RULE_CREATE_FLAG_L2_ENCAP (1<<7) /**< consists of an encapsulating protocol that carries an IPv4 payload within it. */ -#define SFE_RULE_CREATE_FLAG_MC_JOIN (1<<8) /**< Interface has joined the flow */ -#define SFE_RULE_CREATE_FLAG_MC_LEAVE (1<<9) /**< Interface has left the flow */ -#define SFE_RULE_CREATE_FLAG_MC_UPDATE (1<<10)/**< Multicast Rule update */ -/** - * Rule creation validity flags. - */ -#define SFE_RULE_CREATE_CONN_VALID (1<<0) /**< IPv4 Connection is valid */ -#define SFE_RULE_CREATE_TCP_VALID (1<<1) /**< TCP Protocol fields are valid */ -#define SFE_RULE_CREATE_PPPOE_VALID (1<<2) /**< PPPoE fields are valid */ -#define SFE_RULE_CREATE_QOS_VALID (1<<3) /**< QoS fields are valid */ -#define SFE_RULE_CREATE_VLAN_VALID (1<<4) /**< VLAN fields are valid */ -#define SFE_RULE_CREATE_DSCP_MARKING_VALID (1<<5) /**< DSCP marking fields are valid */ -#define SFE_RULE_CREATE_VLAN_MARKING_VALID (1<<6) /**< VLAN marking fields are valid */ -#define SFE_RULE_CREATE_MC_NAT_VALID (1<<7) /**< Interface is configured with Source-NAT */ -#define SFE_RULE_CREATE_DIRECTION_VALID (1<<8) /**< specify acceleration directions */ - -/* - * 32/64 bits pointer type - */ -#ifdef __LP64__ -typedef uint64_t sfe_ptr_t; -#else -typedef uint32_t sfe_ptr_t; -#endif - -typedef enum sfe_rule_sync_reason { - SFE_RULE_SYNC_REASON_STATS, /* Sync is to synchronize stats */ - SFE_RULE_SYNC_REASON_FLUSH, /* Sync is to flush a entry */ - SFE_RULE_SYNC_REASON_EVICT, /* Sync is to evict a entry */ - SFE_RULE_SYNC_REASON_DESTROY /* Sync is to destroy a entry(requested by connection manager) */ - -} sfe_rule_sync_reason_t; - -/** - * Tx command status - */ -typedef enum { - SFE_TX_SUCCESS = 0, /**< Success */ - SFE_TX_FAILURE, /**< Command failure other than descriptor not available */ - SFE_TX_FAILURE_QUEUE, /**< Command failure due to descriptor not available */ - SFE_TX_FAILURE_NOT_READY, /**< Command failure due to SFE state uninitialized */ - SFE_TX_FAILURE_TOO_LARGE, /**< Command is too large to fit in one message */ - SFE_TX_FAILURE_TOO_SHORT, /**< Command/Packet is shorter than expected size */ - SFE_TX_FAILURE_NOT_SUPPORTED, /**< Command/Packet not accepted for forwarding */ - SFE_TX_FAILURE_BAD_PARAM, /**< Command failure due to bad parameters */ - SFE_TX_FAILURE_NOT_ENABLED, /**< Command failure due to SFE feature is not enabled */ -} sfe_tx_status_t; - -/** - * Common response structure - */ -enum sfe_cmn_response { - SFE_CMN_RESPONSE_ACK, /**< Message Acknowledge */ - SFE_CMN_RESPONSE_EVERSION, /**< Message Version Error */ - SFE_CMN_RESPONSE_EINTERFACE, /**< Message Interface Error */ - SFE_CMN_RESPONSE_ELENGTH, /**< Message Length Error */ - SFE_CMN_RESPONSE_EMSG, /**< Message Error */ - SFE_CMM_RESPONSE_NOTIFY, /**< Message Independant of Request */ - SFE_CMN_RESPONSE_LAST -}; - -/** - * IPv4 bridge/route rule messages - */ -enum sfe_message_types { - SFE_TX_CREATE_RULE_MSG, /**< IPv4/6 create rule message */ - SFE_TX_DESTROY_RULE_MSG, /**< IPv4/6 destroy rule message */ - SFE_RX_CONN_STATS_SYNC_MSG, /**< IPv4/6 connection stats sync message */ - SFE_TX_CREATE_MC_RULE_MSG, /**< IPv4/6 multicast create rule message */ - SFE_TUN6RD_ADD_UPDATE_PEER, /**< Add/update peer for 6rd tunnel */ - SFE_MAX_MSG_TYPES, /**< IPv4/6 message max type number */ -}; - -/** - * Common message structure - */ -struct sfe_cmn_msg { - u16 version; /**< Version id for main message format */ - u16 interface; /**< Primary Key for all messages */ - enum sfe_cmn_response response; /**< Primary response */ - u32 type; /**< Decetralized request #, to be used to match response # */ - u32 error; /**< Decentralized specific error message, response == EMSG */ - sfe_ptr_t cb; /**< Place for callback pointer */ - sfe_ptr_t app_data; /**< Place for app data */ - u32 len; /**< What is the length of the message excluding this header */ -}; - -/** - * Common 5 tuple structure - */ -struct sfe_ipv4_5tuple { - __be32 flow_ip; /**< Flow IP address */ - __be32 return_ip; /**< Return IP address */ - __be16 flow_ident; /**< Flow ident (e.g. TCP/UDP port) */ - __be16 return_ident; /**< Return ident (e.g. TCP/UDP port) */ - u8 protocol; /**< Protocol number */ - u8 reserved[3]; /**< Padded for alignment */ -}; - -/** - * Common 5 tuple structure - */ -struct sfe_ipv6_5tuple { - __be32 flow_ip[4]; /**< Flow IP address */ - __be32 return_ip[4]; /**< Return IP address */ - __be16 flow_ident; /**< Flow ident (e.g. TCP/UDP port) */ - __be16 return_ident; /**< Return ident (e.g. TCP/UDP port) */ - u8 protocol; /**< Protocol number */ - u8 reserved[3]; /**< Padded for alignment */ -}; - -/** - * Connection create structure - */ -struct sfe_ipv4_connection_rule { - u8 flow_mac[6]; /**< Flow MAC address */ - u8 return_mac[6]; /**< Return MAC address */ - s32 flow_interface_num; /**< Flow interface number */ - s32 return_interface_num; /**< Return interface number */ - s32 flow_top_interface_num; /* Top flow interface number */ - s32 return_top_interface_num;/* Top return interface number */ - u32 flow_mtu; /**< Flow interface`s MTU */ - u32 return_mtu; /**< Return interface`s MTU */ - __be32 flow_ip_xlate; /**< Translated flow IP address */ - __be32 return_ip_xlate; /**< Translated return IP address */ - __be16 flow_ident_xlate; /**< Translated flow ident (e.g. port) */ - __be16 return_ident_xlate; /**< Translated return ident (e.g. port) */ -}; - -/** - * Connection create structure - */ -struct sfe_ipv6_connection_rule { - u8 flow_mac[6]; /**< Flow MAC address */ - u8 return_mac[6]; /**< Return MAC address */ - s32 flow_interface_num; /**< Flow interface number */ - s32 return_interface_num; /**< Return interface number */ - s32 flow_top_interface_num; /* Top flow interface number */ - s32 return_top_interface_num;/* Top return interface number */ - u32 flow_mtu; /**< Flow interface's MTU */ - u32 return_mtu; /**< Return interface's MTU */ -}; - -/** - * TCP connection rule structure - */ -struct sfe_protocol_tcp_rule { - u32 flow_max_window; /**< Flow direction's largest seen window */ - u32 return_max_window; /**< Return direction's largest seen window */ - u32 flow_end; /**< Flow direction's largest seen sequence + segment length */ - u32 return_end; /**< Return direction's largest seen sequence + segment length */ - u32 flow_max_end; /**< Flow direction's largest seen ack + max(1, win) */ - u32 return_max_end; /**< Return direction's largest seen ack + max(1, win) */ - u8 flow_window_scale; /**< Flow direction's window scaling factor */ - u8 return_window_scale; /**< Return direction's window scaling factor */ - u16 reserved; /**< Padded for alignment */ -}; - -/** - * PPPoE connection rules structure - */ -struct sfe_pppoe_rule { - u16 flow_pppoe_session_id; /**< Flow direction`s PPPoE session ID. */ - u16 flow_pppoe_remote_mac[3]; /**< Flow direction`s PPPoE Server MAC address */ - u16 return_pppoe_session_id; /**< Return direction's PPPoE session ID. */ - u16 return_pppoe_remote_mac[3]; /**< Return direction's PPPoE Server MAC address */ -}; - -/** - * QoS connection rule structure - */ -struct sfe_qos_rule { - u32 flow_qos_tag; /**< QoS tag associated with this rule for flow direction */ - u32 return_qos_tag; /**< QoS tag associated with this rule for return direction */ -}; - -/** - * DSCP connection rule structure - */ -struct sfe_dscp_rule { - u8 flow_dscp; /**< Egress DSCP value for flow direction */ - u8 return_dscp; /**< Egress DSCP value for return direction */ - u8 reserved[2]; /**< Padded for alignment */ -}; - -/** - * VLAN connection rule structure - */ -struct sfe_vlan_rule { - u32 ingress_vlan_tag; /**< VLAN Tag for the ingress packets */ - u32 egress_vlan_tag; /**< VLAN Tag for egress packets */ -}; - -/** - * Acceleration direction rule structure - * Sometimes we just want to accelerate traffic in one direction but not in another. - */ -struct sfe_acceleration_direction_rule { - u8 flow_accel; /**< Accelerate in flow direction */ - u8 return_accel; /**< Accelerate in return direction */ - u8 reserved[2]; /**< Padded for alignment */ -}; - -/** - * The IPv4 rule create sub-message structure. - */ -struct sfe_ipv4_rule_create_msg { - /* Request */ - u16 valid_flags; /**< Bit flags associated with the validity of parameters */ - u16 rule_flags; /**< Bit flags associated with the rule */ - - struct sfe_ipv4_5tuple tuple; /**< Holds values of the 5 tuple */ - - struct sfe_ipv4_connection_rule conn_rule; /**< Basic connection specific data */ - struct sfe_protocol_tcp_rule tcp_rule; /**< TCP related accleration parameters */ - struct sfe_pppoe_rule pppoe_rule; /**< PPPoE related accleration parameters */ - struct sfe_qos_rule qos_rule; /**< QoS related accleration parameters */ - struct sfe_dscp_rule dscp_rule; /**< DSCP related accleration parameters */ - struct sfe_vlan_rule vlan_primary_rule; /**< Primary VLAN related accleration parameters */ - struct sfe_vlan_rule vlan_secondary_rule; /**< Secondary VLAN related accleration parameters */ -#ifdef CONFIG_XFRM - struct sfe_acceleration_direction_rule direction_rule;/* Direction related accleration parameters*/ -#endif - /* Response */ - u32 index; /**< Slot ID for cache stats to host OS */ -}; - -/** - * The IPv4 rule destroy sub-message structure. - */ -struct sfe_ipv4_rule_destroy_msg { - struct sfe_ipv4_5tuple tuple; /**< Holds values of the 5 tuple */ -}; - -/** - * The SFE IPv4 rule sync structure. - */ -struct sfe_ipv4_conn_sync { - u32 index; /**< Slot ID for cache stats to host OS */ - u8 protocol; /**< Protocol number */ - __be32 flow_ip; /**< Flow IP address */ - __be32 flow_ip_xlate; /**< Translated flow IP address */ - __be16 flow_ident; /**< Flow ident (e.g. port) */ - __be16 flow_ident_xlate; /**< Translated flow ident (e.g. port) */ - u32 flow_max_window; /**< Flow direction's largest seen window */ - u32 flow_end; /**< Flow direction's largest seen sequence + segment length */ - u32 flow_max_end; /**< Flow direction's largest seen ack + max(1, win) */ - u32 flow_rx_packet_count; /**< Flow interface's RX packet count */ - u32 flow_rx_byte_count; /**< Flow interface's RX byte count */ - u32 flow_tx_packet_count; /**< Flow interface's TX packet count */ - u32 flow_tx_byte_count; /**< Flow interface's TX byte count */ - u16 flow_pppoe_session_id; /**< Flow interface`s PPPoE session ID. */ - u16 flow_pppoe_remote_mac[3]; - /**< Flow interface's PPPoE remote server MAC address if there is any */ - __be32 return_ip; /**< Return IP address */ - __be32 return_ip_xlate; /**< Translated return IP address */ - __be16 return_ident; /**< Return ident (e.g. port) */ - __be16 return_ident_xlate; /**< Translated return ident (e.g. port) */ - u32 return_max_window; /**< Return direction's largest seen window */ - u32 return_end; /**< Return direction's largest seen sequence + segment length */ - u32 return_max_end; /**< Return direction's largest seen ack + max(1, win) */ - u32 return_rx_packet_count; - /**< Return interface's RX packet count */ - u32 return_rx_byte_count; /**< Return interface's RX byte count */ - u32 return_tx_packet_count; - /**< Return interface's TX packet count */ - u32 return_tx_byte_count; /**< Return interface's TX byte count */ - u16 return_pppoe_session_id; - /**< Return interface`s PPPoE session ID. */ - u16 return_pppoe_remote_mac[3]; - /**< Return interface's PPPoE remote server MAC address if there is any */ - u32 inc_ticks; /**< Number of ticks since the last sync */ - u32 reason; /**< Reason for the sync */ - - u8 flags; /**< Bit flags associated with the rule */ - u32 qos_tag; /**< QoS Tag */ - u32 cause; /**< Flush Cause */ -}; - -/* - * Message structure to send/receive IPv4 bridge/route commands - */ -struct sfe_ipv4_msg { - struct sfe_cmn_msg cm; /**< Message Header */ - union { - struct sfe_ipv4_rule_create_msg rule_create; /**< Message: rule create */ - struct sfe_ipv4_rule_destroy_msg rule_destroy; /**< Message: rule destroy */ - struct sfe_ipv4_conn_sync conn_stats; /**< Message: connection stats sync */ - } msg; -}; - -/** - * Callback to be called when IPv4 message is received - */ -typedef void (*sfe_ipv4_msg_callback_t)(void *app_data, struct sfe_ipv4_msg *msg); - -/** - * The IPv6 rule create sub-message structure. - */ -struct sfe_ipv6_rule_create_msg { - /* - * Request - */ - u16 valid_flags; /**< Bit flags associated with the validity of parameters */ - u16 rule_flags; /**< Bit flags associated with the rule */ - struct sfe_ipv6_5tuple tuple; /**< Holds values of the 5 tuple */ - struct sfe_ipv6_connection_rule conn_rule; /**< Basic connection specific data */ - struct sfe_protocol_tcp_rule tcp_rule; /**< Protocol related accleration parameters */ - struct sfe_pppoe_rule pppoe_rule; /**< PPPoE related accleration parameters */ - struct sfe_qos_rule qos_rule; /**< QoS related accleration parameters */ - struct sfe_dscp_rule dscp_rule; /**< DSCP related accleration parameters */ - struct sfe_vlan_rule vlan_primary_rule; /**< VLAN related accleration parameters */ - struct sfe_vlan_rule vlan_secondary_rule; /**< VLAN related accleration parameters */ -#ifdef CONFIG_XFRM - struct sfe_acceleration_direction_rule direction_rule;/* Direction related accleration parameters*/ -#endif - /* - * Response - */ - u32 index; /**< Slot ID for cache stats to host OS */ -}; - -/** - * The IPv6 rule destroy sub-message structure. - */ -struct sfe_ipv6_rule_destroy_msg { - struct sfe_ipv6_5tuple tuple; /**< Holds values of the 5 tuple */ -}; - -/** - * The SFE IPv6 rule sync structure. - */ -struct sfe_ipv6_conn_sync { - u32 index; /**< Slot ID for cache stats to host OS */ - u8 protocol; /**< Protocol number */ - __be32 flow_ip[4]; /**< Flow IP address */ - __be16 flow_ident; /**< Flow ident (e.g. port) */ - u32 flow_max_window; /**< Flow direction's largest seen window */ - u32 flow_end; /**< Flow direction's largest seen sequence + segment length */ - u32 flow_max_end; /**< Flow direction's largest seen ack + max(1, win) */ - u32 flow_rx_packet_count; /**< Flow interface's RX packet count */ - u32 flow_rx_byte_count; /**< Flow interface's RX byte count */ - u32 flow_tx_packet_count; /**< Flow interface's TX packet count */ - u32 flow_tx_byte_count; /**< Flow interface's TX byte count */ - u16 flow_pppoe_session_id; /**< Flow interface`s PPPoE session ID. */ - u16 flow_pppoe_remote_mac[3]; - /**< Flow interface's PPPoE remote server MAC address if there is any */ - __be32 return_ip[4]; /**< Return IP address */ - __be16 return_ident; /**< Return ident (e.g. port) */ - u32 return_max_window; /**< Return direction's largest seen window */ - u32 return_end; /**< Return direction's largest seen sequence + segment length */ - u32 return_max_end; /**< Return direction's largest seen ack + max(1, win) */ - u32 return_rx_packet_count; - /**< Return interface's RX packet count */ - u32 return_rx_byte_count; /**< Return interface's RX byte count */ - u32 return_tx_packet_count; - /**< Return interface's TX packet count */ - u32 return_tx_byte_count; /**< Return interface's TX byte count */ - u16 return_pppoe_session_id; - /**< Return interface`s PPPoE session ID. */ - u16 return_pppoe_remote_mac[3]; - /**< Return interface's PPPoE remote server MAC address if there is any */ - u32 inc_ticks; /**< Number of ticks since the last sync */ - u32 reason; /**< Reason for the sync */ - u8 flags; /**< Bit flags associated with the rule */ - u32 qos_tag; /**< QoS Tag */ - u32 cause; /**< Flush cause associated with the rule */ -}; - -/** - * Message structure to send/receive IPv6 bridge/route commands - */ -struct sfe_ipv6_msg { - struct sfe_cmn_msg cm; /**< Message Header */ - union { - struct sfe_ipv6_rule_create_msg rule_create; /**< Message: rule create */ - struct sfe_ipv6_rule_destroy_msg rule_destroy; /**< Message: rule destroy */ - struct sfe_ipv6_conn_sync conn_stats; /**< Message: stats sync */ - } msg; -}; - -/** - * Callback to be called when IPv6 message is received - */ -typedef void (*sfe_ipv6_msg_callback_t)(void *app_data, struct sfe_ipv6_msg *msg); - -/** - * 6rd tunnel peer addr. - */ -struct sfe_tun6rd_set_peer_msg { - __be32 ipv6_address[4]; /* The peer's ipv6 addr*/ - __be32 dest; /* The peer's ipv4 addr*/ -}; - -/** - * Message structure to send/receive 6rd tunnel messages - */ -struct sfe_tun6rd_msg { - struct sfe_cmn_msg cm; /* Message Header */ - union { - struct sfe_tun6rd_set_peer_msg peer; /* Message: add/update peer */ - } msg; -}; - -/* - * sfe driver context instance - */ -struct sfe_drv_ctx_instance { - int not_used; -}; - -/* - * sfe_drv_ipv4_max_conn_count() - * Return the maximum number of IPv4 connections that the sfe acceleration engine supports - * - * @return int The number of connections that can be accelerated by the sfe - */ -int sfe_drv_ipv4_max_conn_count(void); - -/* - * sfe_drv_ipv4_tx() - * Transmit an IPv4 message to the sfe - * - * @param sfe_drv_ctx sfe driver context - * @param msg The IPv4 message - * - * @return sfe_tx_status_t The status of the Tx operation - */ -extern sfe_tx_status_t sfe_drv_ipv4_tx(struct sfe_drv_ctx_instance *sfe_drv_ctx, struct sfe_ipv4_msg *msg); - -/* - * sfe_drv_ipv4_notify_register() - * Register a notifier callback for IPv4 messages from sfe driver - * - * @param cb The callback pointer - * @param app_data The application context for this message - * - * @return struct sfe_drv_ctx_instance * The sfe driver context - */ -extern struct sfe_drv_ctx_instance *sfe_drv_ipv4_notify_register(sfe_ipv4_msg_callback_t cb, void *app_data); - -/* - * sfe_drv_ipv4_notify_unregister() - * Un-Register a notifier callback for IPv4 messages from sfe driver - */ -extern void sfe_drv_ipv4_notify_unregister(void); - -/* - * sfe_ipv4_msg_init() - * IPv4 message init - */ -extern void sfe_ipv4_msg_init(struct sfe_ipv4_msg *nim, u16 if_num, u32 type, u32 len, - sfe_ipv4_msg_callback_t cb, void *app_data); - -/* - * sfe_drv_ipv6_max_conn_count() - * Return the maximum number of IPv6 connections that the sfe acceleration engine supports - * - * @return int The number of connections that can be accelerated by the sfe - */ -int sfe_drv_ipv6_max_conn_count(void); - -/* - * sfe_drv_ipv6_tx() - * Transmit an IPv6 message to the sfe - * - * @param sfe_drv_ctx sfe driver context - * @param msg The IPv6 message - * - * @return sfe_tx_status_t The status of the Tx operation - */ -extern sfe_tx_status_t sfe_drv_ipv6_tx(struct sfe_drv_ctx_instance *sfe_drv_ctx, struct sfe_ipv6_msg *msg); - -/* - * sfe_drv_ipv6_notify_register() - * Register a notifier callback for IPv6 messages from sfe driver - * - * @param cb The callback pointer - * @param app_data The application context for this message - * - * @return struct sfe_drv_ctx_instance * The sfe driver context - */ -extern struct sfe_drv_ctx_instance *sfe_drv_ipv6_notify_register(sfe_ipv6_msg_callback_t cb, void *app_data); - -/* - * sfe_drv_ipv6_notify_unregister() - * Un-Register a notifier callback for IPv6 messages from sfe driver - */ -extern void sfe_drv_ipv6_notify_unregister(void); - -/* - * sfe_ipv6_msg_init() - * IPv6 message init - */ -extern void sfe_ipv6_msg_init(struct sfe_ipv6_msg *nim, u16 if_num, u32 type, u32 len, - sfe_ipv6_msg_callback_t cb, void *app_data); - -/* - * sfe_tun6rd_tx() - * Transmit a tun6rd message to sfe engine - */ -sfe_tx_status_t sfe_tun6rd_tx(struct sfe_drv_ctx_instance *sfe_ctx, struct sfe_tun6rd_msg *msg); - -/* - * sfe_tun6rd_msg_init() - * Initialize sfe_tun6rd msg. - */ -void sfe_tun6rd_msg_init(struct sfe_tun6rd_msg *ncm, u16 if_num, u32 type, u32 len, - void *cb, void *app_data); - -#endif /* __SFE_DRV_H */