shortcut-fe: make APIs more general
make APIs between connection manager and core engine more general,
then we can operate on IPv6 using same APIs.
CRs-Fixed: 818271
Change-Id: I48937ae325453b7abb8674e77cecf519a3a24d9f
Signed-off-by: Xiaoping Fan <xfan@codeaurora.org>
diff --git a/shortcut-fe/sfe_cm.c b/shortcut-fe/sfe_cm.c
index 601749d..1e18c15 100644
--- a/shortcut-fe/sfe_cm.c
+++ b/shortcut-fe/sfe_cm.c
@@ -2,7 +2,7 @@
* sfe-cm.c
* Shortcut forwarding engine connection manager.
*
- * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ * Copyright (c) 2013-2015 Qualcomm Atheros, Inc.
*
* All Rights Reserved.
* Qualcomm Atheros Confidential and Proprietary.
@@ -21,7 +21,7 @@
#include <linux/if_bridge.h>
#include "sfe.h"
-#include "sfe_ipv4.h"
+#include "sfe_cm.h"
#include "sfe_backport.h"
/*
@@ -119,66 +119,83 @@
* structure, obtain the hardware address. This means this function also
* works if the neighbours are routers too.
*/
-static bool sfe_cm_find_dev_and_mac_addr(uint32_t addr, struct net_device **dev, uint8_t *mac_addr)
+static bool sfe_cm_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct net_device **dev, uint8_t *mac_addr, int is_v4)
{
struct neighbour *neigh;
struct rtable *rt;
struct dst_entry *dst;
struct net_device *mac_dev;
+ if (unlikely(!is_v4)) {
+ /*
+ * will support IPv6 soon
+ */
+ goto ret_fail;
+ }
+
/*
* Look up the rtable entry for the IP address then get the hardware
* address from its neighbour structure. This means this work when the
* neighbours are routers too.
*/
- rt = ip_route_output(&init_net, addr, 0, 0, 0);
+ rt = ip_route_output(&init_net, addr->ip, 0, 0, 0);
if (unlikely(IS_ERR(rt))) {
- return false;
+ goto ret_fail;
}
dst = (struct dst_entry *)rt;
rcu_read_lock();
- neigh = dst_neigh_lookup(dst, &addr);
+ neigh = dst_neigh_lookup(dst, addr);
if (unlikely(!neigh)) {
rcu_read_unlock();
dst_release(dst);
- return false;
+ goto ret_fail;
}
if (unlikely(!(neigh->nud_state & NUD_VALID))) {
- neigh_release(neigh);
rcu_read_unlock();
+ neigh_release(neigh);
dst_release(dst);
- return false;
+ goto ret_fail;
}
mac_dev = neigh->dev;
if (!mac_dev) {
- neigh_release(neigh);
rcu_read_unlock();
+ neigh_release(neigh);
dst_release(dst);
- return false;
+ goto ret_fail;
}
memcpy(mac_addr, neigh->ha, (size_t)mac_dev->addr_len);
dev_hold(mac_dev);
*dev = mac_dev;
- neigh_release(neigh);
rcu_read_unlock();
+ neigh_release(neigh);
dst_release(dst);
return true;
+
+ret_fail:
+ if (is_v4) {
+ DEBUG_TRACE("failed to find MAC address for IP: %pI4\n", &addr->ip);
+
+ } else {
+ DEBUG_TRACE("failed to find MAC address for IP: %pI6\n", addr->ip6);
+ }
+
+ return false;
}
/*
- * sfe_cm_ipv4_post_routing_hook()
+ * sfe_cm_post_routing()
* Called for packets about to leave the box - either locally generated or forwarded from another interface
*/
-sfe_cm_ipv4_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn)
+static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4)
{
- struct sfe_ipv4_create sic;
+ struct sfe_connection_create sic;
struct net_device *in;
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
@@ -251,21 +268,28 @@
/*
* Get addressing information, non-NAT first
*/
- sic.src_ip = (__be32)orig_tuple.src.u3.ip;
- sic.dest_ip = (__be32)orig_tuple.dst.u3.ip;
+ if (likely(is_v4)) {
+ sic.src_ip.ip = (__be32)orig_tuple.src.u3.ip;
+ sic.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip;
- if (ipv4_is_multicast(sic.src_ip) || ipv4_is_multicast(sic.dest_ip)) {
- DEBUG_TRACE("multicast address\n");
+ if (ipv4_is_multicast(sic.src_ip.ip) || ipv4_is_multicast(sic.dest_ip.ip)) {
+ DEBUG_TRACE("multicast address\n");
+ return NF_ACCEPT;
+ }
+
+ /*
+ * NAT'ed addresses - note these are as seen from the 'reply' direction
+ * When NAT does not apply to this connection these will be identical to the above.
+ */
+ sic.src_ip_xlate.ip = (__be32)reply_tuple.dst.u3.ip;
+ sic.dest_ip_xlate.ip = (__be32)reply_tuple.src.u3.ip;
+ } else {
+ /*
+ * will support soon
+ */
return NF_ACCEPT;
}
- /*
- * NAT'ed addresses - note these are as seen from the 'reply' direction
- * When NAT does not apply to this connection these will be identical to the above.
- */
- sic.src_ip_xlate = (__be32)reply_tuple.dst.u3.ip;
- sic.dest_ip_xlate = (__be32)reply_tuple.src.u3.ip;
-
sic.flags = 0;
switch (sic.protocol) {
@@ -285,7 +309,7 @@
if (nf_ct_tcp_no_window_check
|| (ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_BE_LIBERAL)
|| (ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) {
- sic.flags |= SFE_IPV4_CREATE_FLAG_NO_SEQ_CHECK;
+ sic.flags |= SFE_CREATE_FLAG_NO_SEQ_CHECK;
}
/*
@@ -328,27 +352,23 @@
* Get the net device and MAC addresses that correspond to the various source and
* destination host addresses.
*/
- if (!sfe_cm_find_dev_and_mac_addr(sic.src_ip, &src_dev, sic.src_mac)) {
- DEBUG_TRACE("failed to find MAC address for src IP: %pI4\n", &sic.src_ip);
+ if (!sfe_cm_find_dev_and_mac_addr(&sic.src_ip, &src_dev, sic.src_mac, is_v4)) {
return NF_ACCEPT;
}
- if (!sfe_cm_find_dev_and_mac_addr(sic.src_ip_xlate, &dev, sic.src_mac_xlate)) {
- DEBUG_TRACE("failed to find MAC address for xlate src IP: %pI4\n", &sic.src_ip_xlate);
+ if (!sfe_cm_find_dev_and_mac_addr(&sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) {
goto done1;
}
dev_put(dev);
- if (!sfe_cm_find_dev_and_mac_addr(sic.dest_ip, &dev, sic.dest_mac)) {
- DEBUG_TRACE("failed to find MAC address for dest IP: %pI4\n", &sic.dest_ip);
+ if (!sfe_cm_find_dev_and_mac_addr(&sic.dest_ip, &dev, sic.dest_mac, is_v4)) {
goto done1;
}
dev_put(dev);
- if (!sfe_cm_find_dev_and_mac_addr(sic.dest_ip_xlate, &dest_dev, sic.dest_mac_xlate)) {
- DEBUG_TRACE("failed to find MAC address for xlate dest IP: %pI4\n", &sic.dest_ip_xlate);
+ if (!sfe_cm_find_dev_and_mac_addr(&sic.dest_ip_xlate, &dest_dev, sic.dest_mac_xlate, is_v4)) {
goto done1;
}
@@ -433,6 +453,15 @@
return NF_ACCEPT;
}
+/*
+ * sfe_cm_ipv4_post_routing_hook()
+ * Called for packets about to leave the box - either locally generated or forwarded from another interface
+ */
+sfe_cm_ipv4_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn)
+{
+ return sfe_cm_post_routing(skb, true);
+}
+
#ifdef CONFIG_NF_CONNTRACK_EVENTS
/*
* sfe_cm_conntrack_event()
@@ -448,7 +477,7 @@
#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
struct nf_ct_event *item = ptr;
#endif
- struct sfe_ipv4_destroy sid;
+ struct sfe_connection_destroy sid;
struct nf_conn *ct = item->ct;
struct nf_conntrack_tuple orig_tuple;
@@ -491,8 +520,8 @@
* Extract information from the conntrack connection. We're only interested
* in nominal connection information (i.e. we're ignoring any NAT information).
*/
- sid.src_ip = (__be32)orig_tuple.src.u3.ip;
- sid.dest_ip = (__be32)orig_tuple.dst.u3.ip;
+ sid.src_ip.ip = (__be32)orig_tuple.src.u3.ip;
+ sid.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip;
switch (sid.protocol) {
case IPPROTO_TCP:
@@ -536,11 +565,11 @@
* Note: see include/linux/netfilter_ipv4.h for info related to priority levels.
* We want to examine packets after NAT translation and any ALG processing.
*/
-static struct nf_hook_ops sfe_cm_ipv4_ops_post_routing[] __read_mostly = {
+static struct nf_hook_ops sfe_cm_ops_post_routing[] __read_mostly = {
{
.hook = __sfe_cm_ipv4_post_routing_hook,
.owner = THIS_MODULE,
- .pf = PF_INET,
+ .pf = NFPROTO_IPV4,
.hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP_PRI_NAT_SRC + 1,
},
@@ -550,22 +579,29 @@
* sfe_cm_sync_rule()
* Synchronize a connection's state.
*/
-static void sfe_cm_sync_rule(struct sfe_ipv4_sync *sis)
+static void sfe_cm_sync_rule(struct sfe_connection_sync *sis)
{
struct nf_conntrack_tuple_hash *h;
struct nf_conntrack_tuple tuple;
struct nf_conn *ct;
SFE_NF_CONN_ACCT(acct);
+ if (sis->is_v6) {
+ /*
+ * will support soon
+ */
+ return;
+ }
+
/*
* Create a tuple so as to be able to look up a connection
*/
memset(&tuple, 0, sizeof(tuple));
- tuple.src.u3.ip = sis->src_ip;
+ tuple.src.u3.ip = sis->src_ip.ip;
tuple.src.u.all = (__be16)sis->src_port;
tuple.src.l3num = AF_INET;
- tuple.dst.u3.ip = sis->dest_ip;
+ tuple.dst.u3.ip = sis->dest_ip.ip;
tuple.dst.dir = IP_CT_DIR_ORIGINAL;
tuple.dst.protonum = (uint8_t)sis->protocol;
tuple.dst.u.all = (__be16)sis->dest_port;
@@ -591,7 +627,9 @@
* Only update if this is not a fixed timeout
*/
if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) {
+ spin_lock_bh(&ct->lock);
ct->timeout.expires += sis->delta_jiffies;
+ spin_unlock_bh(&ct->lock);
}
acct = nf_conn_acct_find(ct);
@@ -692,7 +730,7 @@
/*
* Register our netfilter hooks.
*/
- result = nf_register_hooks(sfe_cm_ipv4_ops_post_routing, ARRAY_SIZE(sfe_cm_ipv4_ops_post_routing));
+ result = nf_register_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing));
if (result < 0) {
DEBUG_ERROR("can't register nf post routing hook: %d\n", result);
goto exit2;
@@ -726,7 +764,7 @@
#ifdef CONFIG_NF_CONNTRACK_EVENTS
exit3:
#endif
- nf_unregister_hooks(sfe_cm_ipv4_ops_post_routing, ARRAY_SIZE(sfe_cm_ipv4_ops_post_routing));
+ nf_unregister_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing));
exit2:
unregister_inetaddr_notifier(&sc->inet_notifier);
@@ -770,7 +808,7 @@
nf_conntrack_unregister_notifier(&init_net, &sfe_cm_conntrack_notifier);
#endif
- nf_unregister_hooks(sfe_cm_ipv4_ops_post_routing, ARRAY_SIZE(sfe_cm_ipv4_ops_post_routing));
+ nf_unregister_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing));
unregister_inetaddr_notifier(&sc->inet_notifier);
unregister_netdevice_notifier(&sc->dev_notifier);