1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter-feeds.git synced 2025-03-09 15:40:03 +00:00
This commit is contained in:
suyuan 2022-09-10 05:34:53 +08:00
parent db8abcd0bc
commit d43ffd8720
22 changed files with 13548 additions and 233 deletions

5
shortcut-fe/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
# Ouptut files
*.o
*.s

122
shortcut-fe/README Normal file
View file

@ -0,0 +1,122 @@
Shortcut Forwarding Engine
--------------------------
Welcome to "Shortcut" :-)
Here's a quick FAQ:
Q) What is Shortcut?
A) Shortcut is an in-Linux-kernel IP packet forwarding engine. It's designed
to offer very high speed IP packet forwarding based on IP connection tracking.
It's dramatically faster than the standard netfilter-based NAT forwarding path
but is designed to synchronise state back to netfilter/conntrack so that it
doesn't need to deal with all of the complexities of special cases.
Q) What versions of IP does it support?
A) The current version only supports IPv4 but will be extended to support IPv6 in
the future.
Q) What transport protocols does it support?
A) TCP and UDP. It also knows enough about ICMP to spot ICMP error messages
related to TCP and UDP and handle things accordingly.
Q) Is there a design spec for this software?
A) Not at the moment. I'll write one when I get more time. The code is
intended to be a good tutorial though - it's very heavily commented. If you
find yourself reading something and not understanding it then I take that to
mean I've probably not done a sufficently good job of explaining what it's
doing in the comments. Let me know - I will try to fix it :-)
Q) Why was it written?
A) It was written as a demonstration of what can be done to provide high
performance forwarding inside the kernel. There were two initial motivations:
1) To provide a platform to enable research into how QoS analysis systems can
offload work and avoid huge Linux overheads.
2) To provide a tool to investigate the behaviour of various processors, SoCs
and software sets so that we can characterize and design new network processor
SoCs.
Q) How much faster is it than the Linux kernel forwarding path?
A) At the time of pushing this to github it's been tested on a QCA AP135.
This has a Scorpion (QCA Scopion, not the QMC one :-)) SoC, QCA9550. The
SoC's processor is a MIPS74K running at 720 MHz and with a DDR2 memory
subsystem that offers a peak of 600 MT/s (16-bit transfers).
Running IPv4 NAT forwarding of UDP between the board's 2 GMAC ports and
using a SmartBits 200 as a traffic generator Linux is able to forward 70k PPS.
Once the SFE code is invoked this will increase to 350k PPS!
There's also a slightly hacky mode which causes SFE to bypass the Linux
bridge layer, but this isn't really ready for use because it doesn't have
sufficient MAC address checks or integration of statistics back to the
Ethernet bridge, but that runs at 436k PPS.
Q) Are there any diagnostics?
A) Yes, this is a research tool after all! There's a complex way to do this
that's more general purpose and a simple one - here's the simple one:
mknod /dev/sfe c 253 0
The file /dev/sfe is an XML-ish output and provides details of all the
network connections currently being offloaded. It also reports the numbers
of packets that took various "exception" paths within the code. In addition
it provides a summary of the number of connections, attempts to accelerate
connections, cancel accelerations, etc. It also reports the numbers of
packets that were forwarded and not forwarded by the engine and has some
stats on the effectiveness of the hashing algorithm it uses.
Q) How does the code interact with Linux?
A) There are four minor patches required to make this software run with
Linux. These are currently against a 3.3.8 or 3.4.0 kernel:
* (net/core/dev.c) adds a hook to allow packets to be extracted out.
* (net/netfilter/nf_conntrack_proto_tcp.c) exposes a state variable inside
netfilter that's necessary to enable TCP sequence and ACK checking within
the offload path. Note that this specific patch is against the QCA QSDK
patched version of 3.3.8 - there's a slightly braindead "performance"
patch in that kernel, courtesy of the OpenWrt community that makes the
Linux forwarding path slightly faster at the expense of losing
functionality :-(
* (net/Kconfig) adds the shortcut-fe option.
* (net/Makefile) adds the shortcut-fe build support.
Once these are applied and the module is loaded then everything else
is automatic :-) The patches are in this git repo.
Q) Are any of the pieces reused from other projects?
A) Yes! Some of the forwarding concepts are reused from the Ubicom Network
Accelerator that morphed into part of the Akronite NSS. This code has all
been substantially changed though to accomodate Linux's needs.
There are also some pieces that I borrowed from the QCA "FastNAT" software
written by Xiaoping Fan <xfan@qca.qualcomm.com>. Xiaoping's code was the
first actual demonstration within QCA that this in-kernel concept could yield
signficant performance gains.
Enjoy!
Dave Hudson <dhudson@qti.qualcomm.com>

View file

@ -1,109 +1,10 @@
#
# Copyright (c) 2013-2018 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.
#
obj-$(CONFIG_FAST_CLASSIFIER) += fast-classifier.o
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
ifeq ($(SFE_SUPPORT_IPV6),)
SFE_SUPPORT_IPV6=y
endif
ccflags-$(SFE_SUPPORT_IPV6) += -DSFE_SUPPORT_IPV6
PKG_NAME:=fast-classifier
PKG_RELEASE:=6
ccflags-y += -I$(obj)/../shortcut-fe
include $(INCLUDE_DIR)/package.mk
define KernelPackage/fast-classifier/Default
SECTION:=kernel
CATEGORY:=Kernel modules
SUBMENU:=Network Support
DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe
TITLE:=Kernel driver for FAST Classifier
FILES:=$(PKG_BUILD_DIR)/fast-classifier.ko
KCONFIG:= \
CONFIG_NF_CONNTRACK_EVENTS=y \
CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \
CONFIG_NF_CONNTRACK_MARK=y \
CONFIG_XFRM=y
CONFLICTS:=kmod-shortcut-fe-drv kmod-shortcut-fe-cm
endef
define KernelPackage/fast-classifier
$(call KernelPackage/fast-classifier/Default)
endef
define KernelPackage/fast-classifier-noload
$(call KernelPackage/fast-classifier/Default)
endef
define KernelPackage/fast-classifier/Default/description
FAST Classifier talks to SFE to make decisions about offloading connections
endef
define KernelPackage/fast-classifier/description
$(call KernelPackage/fast-classifier/Default/description)
endef
define KernelPackage/fast-classifier-noload/description
$(call KernelPackage/fast-classifier/Default/description)
This package does not load fast-classifier at boot by default
endef
define Package/fast-classifier-example
TITLE:=Example user space program for fast-classifier
DEPENDS:=+libnl +kmod-fast-classifier
endef
define Package/fast-classifier-example/description
Example user space program that communicates with fast
classifier kernel module
endef
HAVE_ECM:=$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-standard)
define Build/Compile/kmod
+$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \
$(KERNEL_MAKE_FLAGS) \
$(PKG_MAKE_FLAGS) \
M="$(PKG_BUILD_DIR)" \
CONFIG_FAST_CLASSIFIER=m \
EXTRA_CFLAGS+="-DSFE_SUPPORT_IPV6" \
$(if $(HAVE_ECM),EXTRA_CFLAGS+="-DCONFIG_SFE_ECM" CONFIG_SFE_ECM=y,) \
modules
endef
define Build/Compile/example
$(TARGET_CC) -o $(PKG_BUILD_DIR)/userspace_fast_classifier \
-I $(PKG_BUILD_DIR) \
-I$(STAGING_DIR)/usr/include/libnl \
-I$(STAGING_DIR)/usr/include/libnl3 \
-lnl-genl-3 -lnl-3 \
$(PKG_BUILD_DIR)/nl_classifier_test.c
endef
define Build/Compile
$(Build/Compile/kmod)
$(if $(CONFIG_PACKAGE_fast-classifier-example),$(Build/Compile/example))
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/fast-classifier.h $(1)/usr/include/
endef
define Package/fast-classifier-example/install
$(INSTALL_DIR) $(1)/sbin
$(CP) $(PKG_BUILD_DIR)/userspace_fast_classifier $(1)/sbin/
endef
$(eval $(call KernelPackage,fast-classifier))
#$(eval $(call KernelPackage,fast-classifier-noload))
#$(eval $(call BuildPackage,fast-classifier-example))
obj ?= .

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,57 @@
/*
* User space header to send message to the fast classifier
*
* Copyright (c) 2013,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 <linux/if_ether.h>
#define FAST_CLASSIFIER_GENL_VERSION (1)
#define FAST_CLASSIFIER_GENL_NAME "FC"
#define FAST_CLASSIFIER_GENL_MCGRP "FC_MCGRP"
#define FAST_CLASSIFIER_GENL_HDRSIZE (0)
enum {
FAST_CLASSIFIER_A_UNSPEC,
FAST_CLASSIFIER_A_TUPLE,
__FAST_CLASSIFIER_A_MAX,
};
#define FAST_CLASSIFIER_A_MAX (__FAST_CLASSIFIER_A_MAX - 1)
enum {
FAST_CLASSIFIER_C_UNSPEC,
FAST_CLASSIFIER_C_OFFLOAD,
FAST_CLASSIFIER_C_OFFLOADED,
FAST_CLASSIFIER_C_DONE,
__FAST_CLASSIFIER_C_MAX,
};
#define FAST_CLASSIFIER_C_MAX (__FAST_CLASSIFIER_C_MAX - 1)
struct fast_classifier_tuple {
unsigned short ethertype;
unsigned char proto;
union {
struct in_addr in;
struct in6_addr in6;
} src_saddr;
union {
struct in_addr in;
struct in6_addr in6;
} dst_saddr;
unsigned short sport;
unsigned short dport;
unsigned char smac[ETH_ALEN];
unsigned char dmac[ETH_ALEN];
};

View file

@ -0,0 +1,281 @@
/*
* Copyright (c) 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 <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <arpa/inet.h>
#define NL_CLASSIFIER_GENL_VERSION 1
#define NL_CLASSIFIER_GENL_FAMILY "FC"
#define NL_CLASSIFIER_GENL_GROUP "FC_MCGRP"
#define NL_CLASSIFIER_GENL_HDRSIZE 0
enum NL_CLASSIFIER_CMD {
NL_CLASSIFIER_CMD_UNSPEC,
NL_CLASSIFIER_CMD_ACCEL,
NL_CLASSIFIER_CMD_ACCEL_OK,
NL_CLASSIFIER_CMD_CONNECTION_CLOSED,
NL_CLASSIFIER_CMD_MAX,
};
enum NL_CLASSIFIER_ATTR {
NL_CLASSIFIER_ATTR_UNSPEC,
NL_CLASSIFIER_ATTR_TUPLE,
NL_CLASSIFIER_ATTR_MAX,
};
union nl_classifier_tuple_ip {
struct in_addr in;
struct in6_addr in6;
};
struct nl_classifier_tuple {
unsigned short af;
unsigned char proto;
union nl_classifier_tuple_ip src_ip;
union nl_classifier_tuple_ip dst_ip;
unsigned short sport;
unsigned short dport;
unsigned char smac[6];
unsigned char dmac[6];
};
struct nl_classifier_instance {
struct nl_sock *sock;
int family_id;
int group_id;
int stop;
};
struct nl_classifier_instance nl_cls_inst;
static struct nla_policy nl_classifier_genl_policy[(NL_CLASSIFIER_ATTR_MAX+1)] = {
[NL_CLASSIFIER_ATTR_TUPLE] = { .type = NLA_UNSPEC },
};
void nl_classifier_dump_nl_tuple(struct nl_classifier_tuple *tuple)
{
char ip_str[64];
printf("protocol = %s\n", (tuple->proto == IPPROTO_UDP) ? "udp" : ((tuple->proto == IPPROTO_TCP) ? "tcp" : "unknown"));
printf("source ip = %s\n", inet_ntop(tuple->af, &tuple->src_ip, ip_str, sizeof(ip_str)));
printf("destination ip = %s\n", inet_ntop(tuple->af, &tuple->dst_ip, ip_str, sizeof(ip_str)));
printf("source port = %d\n", ntohs(tuple->sport));
printf("destination port = %d\n", ntohs(tuple->dport));
}
int nl_classifier_msg_recv(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct genlmsghdr *gnlh = nlmsg_data(nlh);
struct nlattr *attrs[(NL_CLASSIFIER_ATTR_MAX+1)];
genlmsg_parse(nlh, NL_CLASSIFIER_GENL_HDRSIZE, attrs, NL_CLASSIFIER_ATTR_MAX, nl_classifier_genl_policy);
switch (gnlh->cmd) {
case NL_CLASSIFIER_CMD_ACCEL_OK:
printf("Acceleration successful:\n");
nl_classifier_dump_nl_tuple(nla_data(attrs[NL_CLASSIFIER_ATTR_TUPLE]));
return NL_OK;
case NL_CLASSIFIER_CMD_CONNECTION_CLOSED:
printf("Connection is closed:\n");
nl_classifier_dump_nl_tuple(nla_data(attrs[NL_CLASSIFIER_ATTR_TUPLE]));
return NL_OK;
default:
printf("nl classifier received unknow message %d\n", gnlh->cmd);
}
return NL_SKIP;
}
void nl_classifier_offload(struct nl_classifier_instance *inst,
unsigned char proto, unsigned long *src_saddr,
unsigned long *dst_saddr, unsigned short sport,
unsigned short dport, int af)
{
struct nl_msg *msg;
int ret;
struct nl_classifier_tuple classifier_msg;
memset(&classifier_msg, 0, sizeof(classifier_msg));
classifier_msg.af = af;
classifier_msg.proto = proto;
memcpy(&classifier_msg.src_ip, src_saddr, (af == AF_INET ? 4 : 16));
memcpy(&classifier_msg.dst_ip, dst_saddr, (af == AF_INET ? 4 : 16));
classifier_msg.sport = sport;
classifier_msg.dport = dport;
msg = nlmsg_alloc();
if (!msg) {
printf("Unable to allocate message\n");
return;
}
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, inst->family_id,
NL_CLASSIFIER_GENL_HDRSIZE, NLM_F_REQUEST,
NL_CLASSIFIER_CMD_ACCEL, NL_CLASSIFIER_GENL_VERSION);
nla_put(msg, NL_CLASSIFIER_ATTR_TUPLE, sizeof(classifier_msg), &classifier_msg);
ret = nl_send_auto(inst->sock, msg);
if (ret < 0) {
printf("send netlink message failed.\n");
nlmsg_free(msg);
return;
}
nlmsg_free(msg);
printf("nl classifier offload connection successful\n");
}
int nl_classifier_init(struct nl_classifier_instance *inst)
{
int ret;
inst->sock = nl_socket_alloc();
if (!inst->sock) {
printf("Unable to allocation socket.\n");
return -1;
}
genl_connect(inst->sock);
inst->family_id = genl_ctrl_resolve(inst->sock, NL_CLASSIFIER_GENL_FAMILY);
if (inst->family_id < 0) {
printf("Unable to resolve family %s\n", NL_CLASSIFIER_GENL_FAMILY);
goto init_failed;
}
inst->group_id = genl_ctrl_resolve_grp(inst->sock, NL_CLASSIFIER_GENL_FAMILY, NL_CLASSIFIER_GENL_GROUP);
if (inst->group_id < 0) {
printf("Unable to resolve mcast group %s\n", NL_CLASSIFIER_GENL_GROUP);
goto init_failed;
}
ret = nl_socket_add_membership(inst->sock, inst->group_id);
if (ret < 0) {
printf("Unable to add membership\n");
goto init_failed;
}
nl_socket_disable_seq_check(inst->sock);
nl_socket_modify_cb(inst->sock, NL_CB_VALID, NL_CB_CUSTOM, nl_classifier_msg_recv, NULL);
printf("nl classifier init successful\n");
return 0;
init_failed:
if (inst->sock) {
nl_close(inst->sock);
nl_socket_free(inst->sock);
inst->sock = NULL;
}
return -1;
}
void nl_classifier_exit(struct nl_classifier_instance *inst)
{
if (inst->sock) {
nl_close(inst->sock);
nl_socket_free(inst->sock);
inst->sock = NULL;
}
printf("nl classifier exit successful\n");
}
int nl_classifier_parse_arg(int argc, char *argv[], unsigned char *proto, unsigned long *src_saddr,
unsigned long *dst_saddr, unsigned short *sport, unsigned short *dport, int *af)
{
int ret;
unsigned short port;
if (argc < 7) {
printf("help: nl_classifier <v4|v6> <udp|tcp> <source ip> <destination ip> <source port> <destination port>\n");
return -1;
}
if (0 == strncmp(argv[1], "v4", 2)) {
*af = AF_INET;
} else if (0 == strncmp(argv[1], "v6", 2)) {
*af = AF_INET6;
} else {
printf("Address family is not supported");
return -1;
}
if (0 == strncmp(argv[2], "udp", 3)) {
*proto = IPPROTO_UDP;
} else if (0 == strncmp(argv[2], "tcp", 3)) {
*proto = IPPROTO_TCP;
} else {
printf("Protocol is not supported");
return -1;
}
ret = inet_pton(*af, argv[3], src_saddr);
if (ret <= 0) {
printf("source ip has wrong format\n");
return -1;
}
ret = inet_pton(*af, argv[4], dst_saddr);
if (ret <= 0) {
printf("destination ip has wrong format\n");
return -1;
}
port = strtol(argv[5], NULL, 0);
*sport = htons(port);
port = strtol(argv[6], NULL, 0);
*dport = htons(port);
printf("nl classifier parse arguments successful\n");
return 0;
}
int main(int argc, char *argv[])
{
struct nl_classifier_instance *inst = &nl_cls_inst;
unsigned char proto;
unsigned long src_addr[4];
unsigned long dst_addr[4];
unsigned short sport;
unsigned short dport;
int af;
int ret;
ret = nl_classifier_parse_arg(argc, argv, &proto, src_addr, dst_addr, &sport, &dport, &af);
if (ret < 0) {
printf("Failed to parse arguments\n");
return ret;
}
ret = nl_classifier_init(inst);
if (ret < 0) {
printf("Unable to init generic netlink\n");
return ret;
}
nl_classifier_offload(inst, proto, src_addr, dst_addr, sport, dport, af);
/* main loop to listen on message */
while (!inst->stop) {
nl_recvmsgs_default(inst->sock);
}
nl_classifier_exit(inst);
return 0;
}

View file

@ -0,0 +1,232 @@
/*
* Copyright (c) 2013,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 <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <errno.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <fast-classifier.h>
static struct nl_sock *sock;
static struct nl_sock *sock_event;
static int family;
static int grp_id;
static struct nla_policy fast_classifier_genl_policy[FAST_CLASSIFIER_A_MAX + 1] = {
[FAST_CLASSIFIER_A_TUPLE] = { .type = NLA_UNSPEC },
};
void dump_fc_tuple(struct fast_classifier_tuple *fc_msg)
{
char src_str[INET_ADDRSTRLEN];
char dst_str[INET_ADDRSTRLEN];
printf("TUPLE: %d, %s, %s, %d, %d"
" SMAC=%02x:%02x:%02x:%02x:%02x:%02x",
" DMAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
fc_msg->proto,
inet_ntop(AF_INET,
&fc_msg->src_saddr.in.s_addr,
src_str,
INET_ADDRSTRLEN),
inet_ntop(AF_INET,
&fc_msg->dst_saddr.in.s_addr,
dst_str,
INET_ADDRSTRLEN),
fc_msg->sport, fc_msg->dport,
fc_msg->smac[0], fc_msg->smac[1], fc_msg->smac[2],
fc_msg->smac[3], fc_msg->smac[4], fc_msg->smac[5],
fc_msg->dmac[0], fc_msg->dmac[1], fc_msg->dmac[2],
fc_msg->dmac[3], fc_msg->dmac[4], fc_msg->dmac[5]);
}
static int parse_cb(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct genlmsghdr *gnlh = nlmsg_data(nlh);
struct nlattr *attrs[FAST_CLASSIFIER_A_MAX];
genlmsg_parse(nlh, 0, attrs, FAST_CLASSIFIER_A_MAX, fast_classifier_genl_policy);
switch (gnlh->cmd) {
case FAST_CLASSIFIER_C_OFFLOADED:
printf("Got a offloaded message\n");
dump_fc_tuple(nla_data(attrs[FAST_CLASSIFIER_A_TUPLE]));
return NL_OK;
case FAST_CLASSIFIER_C_DONE:
printf("Got a done message\n");
dump_fc_tuple(nla_data(attrs[FAST_CLASSIFIER_A_TUPLE]));
return NL_OK;
}
return NL_SKIP;
}
int fast_classifier_init(void)
{
int err;
sock = nl_socket_alloc();
if (!sock) {
printf("Unable to allocation socket.\n");
return -1;
}
genl_connect(sock);
sock_event = nl_socket_alloc();
if (!sock_event) {
nl_close(sock);
nl_socket_free(sock);
printf("Unable to allocation socket.\n");
return -1;
}
genl_connect(sock_event);
family = genl_ctrl_resolve(sock, FAST_CLASSIFIER_GENL_NAME);
if (family < 0) {
nl_close(sock_event);
nl_close(sock);
nl_socket_free(sock);
nl_socket_free(sock_event);
printf("Unable to resolve family\n");
return -1;
}
grp_id = genl_ctrl_resolve_grp(sock, FAST_CLASSIFIER_GENL_NAME,
FAST_CLASSIFIER_GENL_MCGRP);
if (grp_id < 0) {
printf("Unable to resolve mcast group\n");
return -1;
}
err = nl_socket_add_membership(sock_event, grp_id);
if (err < 0) {
printf("Unable to add membership\n");
return -1;
}
nl_socket_disable_seq_check(sock_event);
nl_socket_modify_cb(sock_event, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL);
return 0;
}
void fast_classifier_close(void)
{
nl_close(sock_event);
nl_close(sock);
nl_socket_free(sock_event);
nl_socket_free(sock);
}
void fast_classifier_ipv4_offload(unsigned char proto, unsigned long src_saddr,
unsigned long dst_saddr, unsigned short sport,
unsigned short dport)
{
struct nl_msg *msg;
int ret;
#ifdef DEBUG
char src_str[INET_ADDRSTRLEN];
char dst_str[INET_ADDRSTRLEN];
#endif
struct fast_classifier_tuple fc_msg;
#ifdef DEBUG
printf("DEBUG: would offload: %d, %s, %s, %d, %d\n", proto,
inet_ntop(AF_INET, &src_saddr, src_str, INET_ADDRSTRLEN),
inet_ntop(AF_INET, &dst_saddr, dst_str, INET_ADDRSTRLEN),
sport, dport);
#endif
fc_msg.proto = proto;
fc_msg.src_saddr.in.s_addr = src_saddr;
fc_msg.dst_saddr.in.s_addr = dst_saddr;
fc_msg.sport = sport;
fc_msg.dport = dport;
fc_msg.smac[0] = 'a';
fc_msg.smac[1] = 'b';
fc_msg.smac[2] = 'c';
fc_msg.smac[3] = 'd';
fc_msg.smac[4] = 'e';
fc_msg.smac[5] = 'f';
fc_msg.dmac[0] = 'f';
fc_msg.dmac[1] = 'e';
fc_msg.dmac[2] = 'd';
fc_msg.dmac[3] = 'c';
fc_msg.dmac[4] = 'b';
fc_msg.dmac[5] = 'a';
if (fast_classifier_init() < 0) {
printf("Unable to init generic netlink\n");
exit(1);
}
msg = nlmsg_alloc();
if (!msg) {
nl_socket_free(sock);
printf("Unable to allocate message\n");
return;
}
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family,
FAST_CLASSIFIER_GENL_HDRSIZE, NLM_F_REQUEST,
FAST_CLASSIFIER_C_OFFLOAD, FAST_CLASSIFIER_GENL_VERSION);
nla_put(msg, 1, sizeof(fc_msg), &fc_msg);
ret = nl_send_auto_complete(sock, msg);
nlmsg_free(msg);
if (ret < 0) {
printf("nlmsg_free failed");
nl_close(sock);
nl_socket_free(sock);
return;
}
ret = nl_wait_for_ack(sock);
if (ret < 0) {
printf("wait for ack failed");
nl_close(sock);
nl_socket_free(sock);
return;
}
}
void fast_classifier_listen_for_messages(void)
{
printf("waiting for netlink events\n");
while (1) {
nl_recvmsgs_default(sock_event);
}
}
int main(int argc, char *argv[])
{
if (fast_classifier_init() < 0) {
printf("Unable to init generic netlink\n");
exit(1);
}
fast_classifier_ipv4_offload('a', 0, 0, 0, 0);
/* this never returns */
fast_classifier_listen_for_messages();
fast_classifier_close();
return 0;
}

View file

@ -0,0 +1,12 @@
diff --git a/net/Kconfig b/net/Kconfig
index 976cb63..4a7b0af 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -236,6 +236,7 @@ source "net/dcb/Kconfig"
source "net/dns_resolver/Kconfig"
source "net/batman-adv/Kconfig"
source "net/openvswitch/Kconfig"
+source "net/shortcut-fe/Kconfig"
config RPS
boolean "RPS"

View file

@ -0,0 +1,10 @@
diff --git a/net/Makefile b/net/Makefile
index 6865dab..a8f0091 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -71,3 +71,5 @@ obj-$(CONFIG_BATMAN_ADV) += batman-adv/
obj-$(CONFIG_NFC) += nfc/
obj-$(CONFIG_OPENVSWITCH) += openvswitch/
obj-$(CONFIG_NET_ACTIVITY_STATS) += activity_stats.o
+obj-$(CONFIG_SHORTCUT_FE) += shortcut-fe/
+

View file

@ -0,0 +1,43 @@
diff --git a/net/core/dev.c b/net/core/dev.c
index d23742f..1f0415f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3168,6 +3168,9 @@ void netdev_rx_handler_unregister(struct net_device *dev)
}
EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
+int (*athrs_fast_nat_recv)(struct sk_buff *skb) __rcu __read_mostly;
+EXPORT_SYMBOL_GPL(athrs_fast_nat_recv);
+
static int __netif_receive_skb(struct sk_buff *skb)
{
struct packet_type *ptype, *pt_prev;
@@ -3177,6 +3180,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
bool deliver_exact = false;
int ret = NET_RX_DROP;
__be16 type;
+ int (*fast_recv)(struct sk_buff *skb);
net_timestamp_check(!netdev_tstamp_prequeue, skb);
@@ -3194,10 +3198,18 @@ static int __netif_receive_skb(struct sk_buff *skb)
skb_reset_transport_header(skb);
skb_reset_mac_len(skb);
- pt_prev = NULL;
-
rcu_read_lock();
+ fast_recv = rcu_dereference(athrs_fast_nat_recv);
+ if (fast_recv) {
+ if (fast_recv(skb)) {
+ rcu_read_unlock();
+ return NET_RX_SUCCESS;
+ }
+ }
+
+ pt_prev = NULL;
+
another_round:
__this_cpu_inc(softnet_data.processed);

View file

@ -0,0 +1,25 @@
--- /home/dhudson/mips-orig/nf_conntrack_proto_tcp.c 2013-05-07 21:32:57.153896922 +0100
+++ nf_conntrack_proto_tcp.c 2013-06-13 16:37:40.137102438 +0100
@@ -27,18 +27,20 @@
#include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_log.h>
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
/* Do not check the TCP window for incoming packets */
-static int nf_ct_tcp_no_window_check __read_mostly = 1;
+int nf_ct_tcp_no_window_check __read_mostly = 0;
+EXPORT_SYMBOL_GPL(nf_ct_tcp_no_window_check);
/* "Be conservative in what you do,
be liberal in what you accept from others."
If it's non-zero, we mark only out of window RST segments as INVALID. */
-static int nf_ct_tcp_be_liberal __read_mostly = 0;
+int nf_ct_tcp_be_liberal __read_mostly = 0;
+EXPORT_SYMBOL_GPL(nf_ct_tcp_be_liberal);
/* If it is set to zero, we disable picking up already established
connections. */
static int nf_ct_tcp_loose __read_mostly = 1;
/* Max number of the retransmitted packets without receiving an (acceptable)

View file

@ -0,0 +1,14 @@
#
# Shortcut forwarding engine
#
config SHORTCUT_FE
tristate "Shortcut Forwarding Engine"
depends on NF_CONNTRACK
---help---
Shortcut is a fast in-kernel packet forwarding engine.
To compile this code as a module, choose M here: the module will be
called shortcut-fe.
If unsure, say N.

View file

@ -1,88 +1,23 @@
#
# Copyright (c) 2013-2018, 2020 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.
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
obj-m += shortcut-fe.o
PKG_NAME:=shortcut-fe
PKG_RELEASE:=8
include $(INCLUDE_DIR)/package.mk
define KernelPackage/shortcut-fe
SECTION:=kernel
CATEGORY:=Kernel modules
SUBMENU:=Network Support
DEPENDS:=@IPV6 +kmod-nf-conntrack
TITLE:=Kernel driver for SFE
FILES:= \
$(PKG_BUILD_DIR)/shortcut-fe.ko \
$(PKG_BUILD_DIR)/shortcut-fe-ipv6.ko
KCONFIG:= \
CONFIG_NF_CONNTRACK_EVENTS=y \
CONFIG_NF_CONNTRACK_TIMEOUT=y \
CONFIG_SHORTCUT_FE=y \
CONFIG_XFRM=y
PROVIDES:=$(PKG_NAME)
AUTOLOAD:=$(call AutoLoad,09,shortcut-fe shortcut-fe-ipv6)
endef
define KernelPackage/shortcut-fe/Description
Shortcut is an in-Linux-kernel IP packet forwarding engine.
endef
define KernelPackage/shortcut-fe/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) ./files/usr/bin/sfe_dump $(1)/usr/bin
endef
HAVE_ECM:=$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-premium-noload)$(CONFIG_PACKAGE_kmod-qca-nss-ecm-standard)
define KernelPackage/shortcut-fe-cm
SECTION:=kernel
CATEGORY:=Kernel modules
SUBMENU:=Network Support
DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe
TITLE:=Kernel driver for SFE
FILES:=$(PKG_BUILD_DIR)/shortcut-fe-cm.ko
KCONFIG:= \
CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y \
CONFIG_NF_CONNTRACK_EVENTS=y \
CONFIG_XFRM=y
CONFLICTS:=kmod-shortcut-fe-drv
endef
define KernelPackage/shortcut-fe-cm/Description
Simple connection manager for the Shortcut forwarding engine.
endef
define Build/Compile
$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \
$(KERNEL_MAKE_FLAGS) \
$(PKG_MAKE_FLAGS) \
M="$(PKG_BUILD_DIR)" \
EXTRA_CFLAGS+="-DSFE_SUPPORT_IPV6" SFE_SUPPORT_IPV6=y \
$(if $(HAVE_ECM),EXTRA_CFLAGS+="-DCONFIG_SFE_ECM" CONFIG_SFE_ECM=y,) \
modules
endef
ifneq ($(CONFIG_PACKAGE_kmod-shortcut-fe)$(CONFIG_PACKAGE_kmod-shortcut-fe-cm),)
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include/shortcut-fe
$(CP) -rf $(PKG_BUILD_DIR)/sfe.h $(1)/usr/include/shortcut-fe
endef
ifdef SFE_SUPPORT_IPV6
obj-m += shortcut-fe-ipv6.o
endif
$(eval $(call KernelPackage,shortcut-fe))
$(eval $(call KernelPackage,shortcut-fe-cm))
obj-m += shortcut-fe-cm.o
shortcut-fe-objs := \
sfe_ipv4.o
ifdef SFE_SUPPORT_IPV6
shortcut-fe-ipv6-objs := \
sfe_ipv6.o
endif
shortcut-fe-cm-objs := \
sfe_cm.o

View file

@ -0,0 +1,114 @@
/*
* sfe.h
* Shortcut forwarding engine.
*
* Copyright (c) 2013-2017 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.
*/
/*
* The following are debug macros used throughout the SFE.
*
* The DEBUG_LEVEL enables the followings based on its value,
* when dynamic debug option is disabled.
*
* 0 = OFF
* 1 = ASSERTS / ERRORS
* 2 = 1 + WARN
* 3 = 2 + INFO
* 4 = 3 + TRACE
*/
#define DEBUG_LEVEL 2
#if (DEBUG_LEVEL < 1)
#define DEBUG_ASSERT(s, ...)
#define DEBUG_ERROR(s, ...)
#else
#define DEBUG_ASSERT(c, s, ...) if (!(c)) { pr_emerg("ASSERT: %s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__); BUG(); }
#define DEBUG_ERROR(s, ...) pr_err("%s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
#if defined(CONFIG_DYNAMIC_DEBUG)
/*
* Compile messages for dynamic enable/disable
*/
#define DEBUG_WARN(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define DEBUG_INFO(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define DEBUG_TRACE(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
/*
* Statically compile messages at different levels
*/
#if (DEBUG_LEVEL < 2)
#define DEBUG_WARN(s, ...)
#else
#define DEBUG_WARN(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
#if (DEBUG_LEVEL < 3)
#define DEBUG_INFO(s, ...)
#else
#define DEBUG_INFO(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
#if (DEBUG_LEVEL < 4)
#define DEBUG_TRACE(s, ...)
#else
#define DEBUG_TRACE(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
#endif
#ifdef CONFIG_NF_FLOW_COOKIE
typedef int (*flow_cookie_set_func_t)(u32 protocol, __be32 src_ip, __be16 src_port,
__be32 dst_ip, __be16 dst_port, u16 flow_cookie);
/*
* sfe_register_flow_cookie_cb
* register a function in SFE to let SFE use this function to configure flow cookie for a flow
*
* Hardware driver which support flow cookie should register a callback function in SFE. Then SFE
* can use this function to configure flow cookie for a flow.
* return: 0, success; !=0, fail
*/
int sfe_register_flow_cookie_cb(flow_cookie_set_func_t cb);
/*
* sfe_unregister_flow_cookie_cb
* unregister function which is used to configure flow cookie for a flow
*
* return: 0, success; !=0, fail
*/
int sfe_unregister_flow_cookie_cb(flow_cookie_set_func_t cb);
typedef int (*sfe_ipv6_flow_cookie_set_func_t)(u32 protocol, __be32 src_ip[4], __be16 src_port,
__be32 dst_ip[4], __be16 dst_port, u16 flow_cookie);
/*
* sfe_ipv6_register_flow_cookie_cb
* register a function in SFE to let SFE use this function to configure flow cookie for a flow
*
* Hardware driver which support flow cookie should register a callback function in SFE. Then SFE
* can use this function to configure flow cookie for a flow.
* return: 0, success; !=0, fail
*/
int sfe_ipv6_register_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb);
/*
* sfe_ipv6_unregister_flow_cookie_cb
* unregister function which is used to configure flow cookie for a flow
*
* return: 0, success; !=0, fail
*/
int sfe_ipv6_unregister_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb);
#endif /*CONFIG_NF_FLOW_COOKIE*/

View file

@ -0,0 +1,195 @@
/*
* sfe_backport.h
* Shortcut forwarding engine compatible header file.
*
* Copyright (c) 2014-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 <linux/version.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
#include <net/netfilter/nf_conntrack_timeout.h>
#else
enum udp_conntrack {
UDP_CT_UNREPLIED,
UDP_CT_REPLIED,
UDP_CT_MAX
};
static inline unsigned int *
nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct,
struct nf_conntrack_l4proto *l4proto)
{
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
struct nf_conn_timeout *timeout_ext;
unsigned int *timeouts;
timeout_ext = nf_ct_timeout_find(ct);
if (timeout_ext)
timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext);
else
timeouts = l4proto->get_timeouts(net);
return timeouts;
#else
return l4proto->get_timeouts(net);
#endif /*CONFIG_NF_CONNTRACK_TIMEOUT*/
}
#endif /*KERNEL_VERSION(3, 7, 0)*/
#endif /*KERNEL_VERSION(3, 4, 0)*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \
static unsigned int FN_NAME(void *priv, \
struct sk_buff *SKB, \
const struct nf_hook_state *state)
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \
static unsigned int FN_NAME(const struct nf_hook_ops *OPS, \
struct sk_buff *SKB, \
const struct net_device *UNUSED, \
const struct net_device *OUT, \
int (*OKFN)(struct sk_buff *))
#else
#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \
static unsigned int FN_NAME(unsigned int HOOKNUM, \
struct sk_buff *SKB, \
const struct net_device *UNUSED, \
const struct net_device *OUT, \
int (*OKFN)(struct sk_buff *))
#endif
#define sfe_cm_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \
sfe_define_post_routing_hook(__sfe_cm_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN)
#define sfe_cm_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \
sfe_define_post_routing_hook(__sfe_cm_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN)
#define fast_classifier_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \
sfe_define_post_routing_hook(__fast_classifier_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN)
#define fast_classifier_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \
sfe_define_post_routing_hook(__fast_classifier_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \
{ \
.hook = fn, \
.pf = NFPROTO_IPV4, \
.hooknum = NF_INET_POST_ROUTING, \
.priority = NF_IP_PRI_NAT_SRC + 1, \
}
#else
#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \
{ \
.hook = fn, \
.owner = THIS_MODULE, \
.pf = NFPROTO_IPV4, \
.hooknum = NF_INET_POST_ROUTING, \
.priority = NF_IP_PRI_NAT_SRC + 1, \
}
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \
{ \
.hook = fn, \
.pf = NFPROTO_IPV6, \
.hooknum = NF_INET_POST_ROUTING, \
.priority = NF_IP_PRI_NAT_SRC + 1, \
}
#else
#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \
{ \
.hook = fn, \
.owner = THIS_MODULE, \
.pf = NFPROTO_IPV6, \
.hooknum = NF_INET_POST_ROUTING, \
.priority = NF_IP6_PRI_NAT_SRC + 1, \
}
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0))
#define SFE_NF_CT_DEFAULT_ZONE (&nf_ct_zone_dflt)
#else
#define SFE_NF_CT_DEFAULT_ZONE NF_CT_DEFAULT_ZONE
#endif
/*
* sfe_dev_get_master
* get master of bridge port, and hold it
*/
static inline struct net_device *sfe_dev_get_master(struct net_device *dev)
{
struct net_device *master;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
rcu_read_lock();
master = netdev_master_upper_dev_get_rcu(dev);
if (master)
dev_hold(master);
rcu_read_unlock();
#else
master = dev->master;
if (master)
dev_hold(master);
#endif
return master;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
#define SFE_DEV_EVENT_PTR(PTR) netdev_notifier_info_to_dev(PTR)
#else
#define SFE_DEV_EVENT_PTR(PTR) (struct net_device *)(PTR)
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
#define SFE_NF_CONN_ACCT(NM) struct nf_conn_acct *NM
#else
#define SFE_NF_CONN_ACCT(NM) struct nf_conn_counter *NM
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
#define SFE_ACCT_COUNTER(NM) ((NM)->counter)
#else
#define SFE_ACCT_COUNTER(NM) (NM)
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
#define sfe_hash_for_each_possible(name, obj, node, member, key) \
hash_for_each_possible(name, obj, member, key)
#else
#define sfe_hash_for_each_possible(name, obj, node, member, key) \
hash_for_each_possible(name, obj, node, member, key)
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
#define sfe_hash_for_each(name, bkt, node, obj, member) \
hash_for_each(name, bkt, obj, member)
#else
#define sfe_hash_for_each(name, bkt, node, obj, member) \
hash_for_each(name, bkt, node, obj, member)
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
#define sfe_dst_get_neighbour(dst, daddr) dst_neigh_lookup(dst, addr)
#else
static inline struct neighbour *
sfe_dst_get_neighbour(struct dst_entry *dst, void *daddr)
{
struct neighbour *neigh = dst_get_neighbour_noref(dst);
if (neigh)
neigh_hold(neigh);
return neigh;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,259 @@
/*
* sfe_cm.h
* Shortcut forwarding engine.
*
* Copyright (c) 2013-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.
*/
/*
* connection flags.
*/
#define SFE_CREATE_FLAG_NO_SEQ_CHECK BIT(0)
/* Indicates that we should not check sequence numbers */
#define SFE_CREATE_FLAG_REMARK_PRIORITY BIT(1)
/* Indicates that we should remark priority of skb */
#define SFE_CREATE_FLAG_REMARK_DSCP BIT(2)
/* Indicates that we should remark DSCP of packet */
/*
* IPv6 address structure
*/
struct sfe_ipv6_addr {
__be32 addr[4];
};
typedef union {
__be32 ip;
struct sfe_ipv6_addr ip6[1];
} sfe_ip_addr_t;
/*
* connection creation structure.
*/
struct sfe_connection_create {
int protocol;
struct net_device *src_dev;
struct net_device *dest_dev;
u32 flags;
u32 src_mtu;
u32 dest_mtu;
sfe_ip_addr_t src_ip;
sfe_ip_addr_t src_ip_xlate;
sfe_ip_addr_t dest_ip;
sfe_ip_addr_t dest_ip_xlate;
__be16 src_port;
__be16 src_port_xlate;
__be16 dest_port;
__be16 dest_port_xlate;
u8 src_mac[ETH_ALEN];
u8 src_mac_xlate[ETH_ALEN];
u8 dest_mac[ETH_ALEN];
u8 dest_mac_xlate[ETH_ALEN];
u8 src_td_window_scale;
u32 src_td_max_window;
u32 src_td_end;
u32 src_td_max_end;
u8 dest_td_window_scale;
u32 dest_td_max_window;
u32 dest_td_end;
u32 dest_td_max_end;
u32 mark;
#ifdef CONFIG_XFRM
u32 original_accel;
u32 reply_accel;
#endif
u32 src_priority;
u32 dest_priority;
u32 src_dscp;
u32 dest_dscp;
};
/*
* connection destruction structure.
*/
struct sfe_connection_destroy {
int protocol;
sfe_ip_addr_t src_ip;
sfe_ip_addr_t dest_ip;
__be16 src_port;
__be16 dest_port;
};
typedef enum sfe_sync_reason {
SFE_SYNC_REASON_STATS, /* Sync is to synchronize stats */
SFE_SYNC_REASON_FLUSH, /* Sync is to flush a entry */
SFE_SYNC_REASON_DESTROY /* Sync is to destroy a entry(requested by connection manager) */
} sfe_sync_reason_t;
/*
* Structure used to sync connection stats/state back within the system.
*
* NOTE: The addresses here are NON-NAT addresses, i.e. the true endpoint addressing.
* 'src' is the creator of the connection.
*/
struct sfe_connection_sync {
struct net_device *src_dev;
struct net_device *dest_dev;
int is_v6; /* Is it for ipv6? */
int protocol; /* IP protocol number (IPPROTO_...) */
sfe_ip_addr_t src_ip; /* Non-NAT source address, i.e. the creator of the connection */
sfe_ip_addr_t src_ip_xlate; /* NATed source address */
__be16 src_port; /* Non-NAT source port */
__be16 src_port_xlate; /* NATed source port */
sfe_ip_addr_t dest_ip; /* Non-NAT destination address, i.e. to whom the connection was created */
sfe_ip_addr_t dest_ip_xlate; /* NATed destination address */
__be16 dest_port; /* Non-NAT destination port */
__be16 dest_port_xlate; /* NATed destination port */
u32 src_td_max_window;
u32 src_td_end;
u32 src_td_max_end;
u64 src_packet_count;
u64 src_byte_count;
u32 src_new_packet_count;
u32 src_new_byte_count;
u32 dest_td_max_window;
u32 dest_td_end;
u32 dest_td_max_end;
u64 dest_packet_count;
u64 dest_byte_count;
u32 dest_new_packet_count;
u32 dest_new_byte_count;
u32 reason; /* reason for stats sync message, i.e. destroy, flush, period sync */
u64 delta_jiffies; /* Time to be added to the current timeout to keep the connection alive */
};
/*
* connection mark structure
*/
struct sfe_connection_mark {
int protocol;
sfe_ip_addr_t src_ip;
sfe_ip_addr_t dest_ip;
__be16 src_port;
__be16 dest_port;
u32 mark;
};
/*
* Expose the hook for the receive processing.
*/
extern int (*athrs_fast_nat_recv)(struct sk_buff *skb);
/*
* Expose what should be a static flag in the TCP connection tracker.
*/
extern int nf_ct_tcp_no_window_check;
/*
* This callback will be called in a timer
* at 100 times per second to sync stats back to
* Linux connection track.
*
* A RCU lock is taken to prevent this callback
* from unregistering.
*/
typedef void (*sfe_sync_rule_callback_t)(struct sfe_connection_sync *);
/*
* IPv4 APIs used by connection manager
*/
int sfe_ipv4_recv(struct net_device *dev, struct sk_buff *skb);
int sfe_ipv4_create_rule(struct sfe_connection_create *sic);
void sfe_ipv4_destroy_rule(struct sfe_connection_destroy *sid);
void sfe_ipv4_destroy_all_rules_for_dev(struct net_device *dev);
void sfe_ipv4_register_sync_rule_callback(sfe_sync_rule_callback_t callback);
void sfe_ipv4_update_rule(struct sfe_connection_create *sic);
void sfe_ipv4_mark_rule(struct sfe_connection_mark *mark);
#ifdef SFE_SUPPORT_IPV6
/*
* IPv6 APIs used by connection manager
*/
int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb);
int sfe_ipv6_create_rule(struct sfe_connection_create *sic);
void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid);
void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev);
void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback);
void sfe_ipv6_update_rule(struct sfe_connection_create *sic);
void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark);
#else
static inline int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb)
{
return 0;
}
static inline int sfe_ipv6_create_rule(struct sfe_connection_create *sic)
{
return 0;
}
static inline void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid)
{
return;
}
static inline void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev)
{
return;
}
static inline void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback)
{
return;
}
static inline void sfe_ipv6_update_rule(struct sfe_connection_create *sic)
{
return;
}
static inline void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark)
{
return;
}
#endif
/*
* sfe_ipv6_addr_equal()
* compare ipv6 address
*
* return: 1, equal; 0, no equal
*/
static inline int sfe_ipv6_addr_equal(struct sfe_ipv6_addr *a,
struct sfe_ipv6_addr *b)
{
return a->addr[0] == b->addr[0] &&
a->addr[1] == b->addr[1] &&
a->addr[2] == b->addr[2] &&
a->addr[3] == b->addr[3];
}
/*
* sfe_ipv4_addr_equal()
* compare ipv4 address
*
* return: 1, equal; 0, no equal
*/
#define sfe_ipv4_addr_equal(a, b) ((u32)(a) == (u32)(b))
/*
* sfe_addr_equal()
* compare ipv4 or ipv6 address
*
* return: 1, equal; 0, no equal
*/
static inline int sfe_addr_equal(sfe_ip_addr_t *a,
sfe_ip_addr_t *b, int is_v4)
{
return is_v4 ? sfe_ipv4_addr_equal(a->ip, b->ip) : sfe_ipv6_addr_equal(a->ip6, b->ip6);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2015,2016 The Linux Foundation. All rights reserved.
# 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.
@ -11,50 +11,11 @@
# 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.
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
obj-m += shortcut-fe-drv.o
PKG_NAME:=shortcut-fe-simulated-driver
PKG_RELEASE:=1
shortcut-fe-drv-objs := \
sfe_drv.o
PKG_SOURCE_URL:=https://source.codeaurora.org/quic/qsdk/oss/lklm/shortcut-fe
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2021-03-17
PKG_SOURCE_VERSION:=697977d8d0ccf0ab596e5692d08608a75dd7f33d
PKG_MIRROR_HASH:=659fa82a431e15af797a6c7069faeee02810453ad8b576c51c29f95a1761a045
include $(INCLUDE_DIR)/package.mk
define KernelPackage/shortcut-fe-drv
SECTION:=kernel
CATEGORY:=Kernel modules
SUBMENU:=Network Support
DEPENDS:=@TARGET_ipq806x||TARGET_ipq807x +kmod-shortcut-fe
KCONFIG:= \
CONFIG_NET_CLS_ACT=y \
CONFIG_XFRM=y
TITLE:=Simulated sfe driver for ECM
FILES:=$(PKG_BUILD_DIR)/simulated-driver/shortcut-fe-drv.ko
endef
define KernelPackage/shortcut-fe-drv/Description
Simulated sfe driver which act as an adapter to convert message
between a connection manager and the SFE core engine.
endef
define Build/Compile
$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \
$(KERNEL_MAKE_FLAGS) \
$(PKG_MAKE_FLAGS) \
M="$(PKG_BUILD_DIR)/simulated-driver" \
EXTRA_CFLAGS="-DSFE_SUPPORT_IPV6" \
modules
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include/shortcut-fe
$(CP) -rf $(PKG_BUILD_DIR)/simulated-driver/sfe_drv.h $(1)/usr/include/shortcut-fe
endef
$(eval $(call KernelPackage,shortcut-fe-drv))

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,553 @@
/*
* 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 */