Skip to contentSkip to conversation

: Keep conntrack/nat protocols in array instead of linked list

PATCH In review Patrick McHardy 1 participant 1 message Sep 21, 2004

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 7/12 : Keep conntrack/nat protocols in array instead of linked list

[email protected], 2004-09-19 16:28:21+02:00, [email protected]
[NETFILTER]: Keep conntrack/nat protocols in array instead of linked list

# This is a BitKeeper generated diff -Nru style patch. #
# ChangeSet
# 2004/09/19 16:28:21+02:00 [email protected]
# [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#
# Signed-off-by: Patrick McHardy <[email protected]>
#

# net/ipv4/netfilter/ip_nat_standalone.c
#   2004/09/19 16:27:55+02:00 [email protected] +5 -10
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_nat_proto_unknown.c
#   2004/09/19 16:27:55+02:00 [email protected] +2 -2
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_nat_proto_udp.c
#   2004/09/19 16:27:55+02:00 [email protected] +1 -1
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_nat_proto_tcp.c
#   2004/09/19 16:27:55+02:00 [email protected] +1 -1
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_nat_proto_icmp.c
#   2004/09/19 16:27:55+02:00 [email protected] +1 -1
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_nat_core.c
#   2004/09/19 16:27:55+02:00 [email protected] +11 -28
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_conntrack_standalone.c
#   2004/09/19 16:27:55+02:00 [email protected] +8 -17
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_conntrack_proto_sctp.c
#   2004/09/19 16:27:55+02:00 [email protected] +0 -1
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# net/ipv4/netfilter/ip_conntrack_core.c
#   2004/09/19 16:27:55+02:00 [email protected] +6 -35
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# include/linux/netfilter_ipv4/ip_nat_protocol.h
#   2004/09/19 16:27:55+02:00 [email protected] +14 -2
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# include/linux/netfilter_ipv4/ip_nat_core.h
#   2004/09/19 16:27:55+02:00 [email protected] +0 -6
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# include/linux/netfilter_ipv4/ip_conntrack_protocol.h
#   2004/09/19 16:27:55+02:00 [email protected] +9 -3
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
# include/linux/netfilter_ipv4/ip_conntrack_core.h
#   2004/09/19 16:27:55+02:00 [email protected] +0 -4
#   [NETFILTER]: Keep conntrack/nat protocols in array instead of linked list
#   
#   Signed-off-by: Patrick McHardy <[email protected]>
# 
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_core.h	2004-09-20 11:58:29 +02:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack_core.h	2004-09-20 11:58:29 +02:00
@@ -16,10 +16,6 @@
 extern void ip_conntrack_cleanup(void);

struct ip_conntrack_protocol;
-extern struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol); -/* Like above, but you already have conntrack read lock. */ -extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol); -extern struct list_head protocol_list;

extern int
ip_ct_get_tuple(const struct iphdr *iph,

include/linux/netfilter_ipv4/ip_conntrack_protocol.h +9 -3
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
@@ -7,9 +7,6 @@
 
 struct ip_conntrack_protocol
 {
-	/* Next pointer. */
-	struct list_head list;
-
 	/* Protocol number. */
 	u_int8_t proto;
 
@@ -58,14 +55,23 @@
 	struct module *me;
 };
 
+#define MAX_IP_CT_PROTO 256
+extern struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO];
+
 /* Protocol registration. */
 extern int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto);
 extern void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto);
 
+static inline struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
+{
+	return ip_ct_protos[protocol];
+}
+
 /* Existing built-in protocols */
 extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp;
 extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
 extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp;
+extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
 extern int ip_conntrack_protocol_tcp_init(void);
 
 /* Log invalid packets */
include/linux/netfilter_ipv4/ip_nat_core.h +0 -6
diff -Nru a/include/linux/netfilter_ipv4/ip_nat_core.h b/include/linux/netfilter_ipv4/ip_nat_core.h
@@ -14,8 +14,6 @@
 				unsigned int hooknum,
 				struct sk_buff **pskb);
 
-extern struct list_head protos;
-
 extern int icmp_reply_translation(struct sk_buff **pskb,
 				  struct ip_conntrack *conntrack,
 				  unsigned int hooknum,
@@ -26,8 +24,4 @@
 extern void place_in_hashes(struct ip_conntrack *conntrack,
 			    struct ip_nat_info *info);
 
-/* Built-in protocols. */
-extern struct ip_nat_protocol ip_nat_protocol_tcp;
-extern struct ip_nat_protocol ip_nat_protocol_udp;
-extern struct ip_nat_protocol ip_nat_protocol_icmp;
 #endif /* _IP_NAT_CORE_H */
include/linux/netfilter_ipv4/ip_nat_protocol.h +14 -2
diff -Nru a/include/linux/netfilter_ipv4/ip_nat_protocol.h b/include/linux/netfilter_ipv4/ip_nat_protocol.h
@@ -9,8 +9,6 @@
 
 struct ip_nat_protocol
 {
-	struct list_head list;
-
 	/* Protocol name */
 	const char *name;
 
@@ -47,9 +45,23 @@
 				    const struct ip_nat_range *range);
 };
 
+#define MAX_IP_NAT_PROTO 256
+extern struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO];
+
 /* Protocol registration. */
 extern int ip_nat_protocol_register(struct ip_nat_protocol *proto);
 extern void ip_nat_protocol_unregister(struct ip_nat_protocol *proto);
+
+static inline struct ip_nat_protocol *ip_nat_find_proto(u_int8_t protocol)
+{
+	return ip_nat_protos[protocol];
+}
+
+/* Built-in protocols. */
+extern struct ip_nat_protocol ip_nat_protocol_tcp;
+extern struct ip_nat_protocol ip_nat_protocol_udp;
+extern struct ip_nat_protocol ip_nat_protocol_icmp;
+extern struct ip_nat_protocol ip_nat_unknown_protocol;
 
 extern int init_protocols(void) __init;
 extern void cleanup_protocols(void);
net/ipv4/netfilter/ip_conntrack_core.c +6 -35

60 lines not on this page · raw message

net/ipv4/netfilter/ip_conntrack_proto_sctp.c +0 -1
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -496,7 +496,6 @@
 }
 
 struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { 
-	.list 		 = { NULL, NULL }, 
 	.proto 		 = IPPROTO_SCTP, 
 	.name 		 = "sctp",
 	.pkt_to_tuple 	 = sctp_pkt_to_tuple, 
net/ipv4/netfilter/ip_conntrack_standalone.c +8 -17
diff -Nru a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -112,7 +112,7 @@
 	if (DIRECTION(hash))
 		return 0;
 
-	proto = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+	proto = ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
 			       .tuple.dst.protonum);
 	IP_NF_ASSERT(proto);
 
@@ -242,7 +242,7 @@
 		   expect->tuple.dst.protonum);
 
 	return print_tuple(s, &expect->tuple,
-			   __ip_ct_find_proto(expect->tuple.dst.protonum));
+			   ip_ct_find_proto(expect->tuple.dst.protonum));
 }
 
 static struct seq_operations exp_seq_ops = {
@@ -823,19 +823,13 @@
 int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
 {
 	int ret = 0;
-	struct list_head *i;
 
 	WRITE_LOCK(&ip_conntrack_lock);
-	list_for_each(i, &protocol_list) {
-		if (((struct ip_conntrack_protocol *)i)->proto
-		    == proto->proto) {
-			ret = -EBUSY;
-			goto out;
-		}
+	if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
+		ret = -EBUSY;
+		goto out;
 	}
-
-	list_prepend(&protocol_list, proto);
-
+	ip_ct_protos[proto->proto] = proto;
  out:
 	WRITE_UNLOCK(&ip_conntrack_lock);
 	return ret;
@@ -844,10 +838,7 @@
 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
 {
 	WRITE_LOCK(&ip_conntrack_lock);
-
-	/* ip_ct_find_proto() returns proto_generic in case there is no protocol 
-	 * helper. So this should be enough - HW */
-	LIST_DELETE(&protocol_list, proto);
+	ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
 	WRITE_UNLOCK(&ip_conntrack_lock);
 	
 	/* Somebody could be still looking at the proto in bh. */
@@ -887,8 +878,8 @@
 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
 EXPORT_SYMBOL(ip_ct_selective_cleanup);
 EXPORT_SYMBOL(ip_ct_refresh_acct);
+EXPORT_SYMBOL(ip_ct_protos);
 EXPORT_SYMBOL(ip_ct_find_proto);
-EXPORT_SYMBOL(__ip_ct_find_proto);
 EXPORT_SYMBOL(ip_ct_find_helper);
 EXPORT_SYMBOL(ip_conntrack_expect_alloc);
 EXPORT_SYMBOL(ip_conntrack_expect_related);
net/ipv4/netfilter/ip_nat_core.c +11 -28
diff -Nru a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
@@ -48,9 +48,8 @@
 
 static struct list_head *bysource;
 static struct list_head *byipsproto;
-LIST_HEAD(protos);
+struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO];
 
-extern struct ip_nat_protocol unknown_nat_protocol;
 
 /* We keep extra hashes for each conntrack, for fast searching. */
 static inline size_t
@@ -103,23 +102,6 @@
 				      oldcheck^0xFFFF));
 }
 
-static inline int cmp_proto(const struct ip_nat_protocol *i, int proto)
-{
-	return i->protonum == proto;
-}
-
-struct ip_nat_protocol *
-find_nat_proto(u_int16_t protonum)
-{
-	struct ip_nat_protocol *i;
-
-	MUST_BE_READ_LOCKED(&ip_nat_lock);
-	i = LIST_FIND(&protos, cmp_proto, struct ip_nat_protocol *, protonum);
-	if (!i)
-		i = &unknown_nat_protocol;
-	return i;
-}
-
 /* Is this tuple already taken? (not by us) */
 int
 ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
@@ -142,7 +124,7 @@
 	 const struct ip_conntrack_manip *manip,
 	 const struct ip_nat_multi_range *mr)
 {
-	struct ip_nat_protocol *proto = find_nat_proto(tuple->dst.protonum);
+	struct ip_nat_protocol *proto = ip_nat_find_proto(tuple->dst.protonum);
 	unsigned int i;
 	struct ip_conntrack_tuple newtuple = { *manip, tuple->dst };
 
@@ -394,7 +376,7 @@
 		 unsigned int hooknum)
 {
 	struct ip_nat_protocol *proto
-		= find_nat_proto(orig_tuple->dst.protonum);
+		= ip_nat_find_proto(orig_tuple->dst.protonum);
 	struct ip_nat_range *rptr;
 	unsigned int i;
 	int ret;
@@ -705,9 +687,8 @@
 	iph = (void *)(*pskb)->data + iphdroff;
 
 	/* Manipulate protcol part. */
-	if (!find_nat_proto(proto)->manip_pkt(pskb,
-					      iphdroff + iph->ihl*4,
-					      manip, maniptype))
+	if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4,
+	                                         manip, maniptype))
 		return 0;
 
 	iph = (void *)(*pskb)->data + iphdroff;
@@ -731,7 +712,7 @@
 	int ret = 1;
 
 	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
-	proto = __ip_ct_find_proto(skb->nh.iph->protocol);
+	proto = ip_ct_find_proto(skb->nh.iph->protocol);
 	if (proto->exp_matches_pkt)
 		ret = proto->exp_matches_pkt(exp, skb);
 
@@ -976,9 +957,11 @@
 
 	/* Sew in builtin protocols. */
 	WRITE_LOCK(&ip_nat_lock);
-	list_append(&protos, &ip_nat_protocol_tcp);
-	list_append(&protos, &ip_nat_protocol_udp);
-	list_append(&protos, &ip_nat_protocol_icmp);
+	for (i = 0; i < MAX_IP_NAT_PROTO; i++)
+		ip_nat_protos[i] = &ip_nat_unknown_protocol;
+	ip_nat_protos[IPPROTO_TCP] = &ip_nat_protocol_tcp;
+	ip_nat_protos[IPPROTO_UDP] = &ip_nat_protocol_udp;
+	ip_nat_protos[IPPROTO_ICMP] = &ip_nat_protocol_icmp;
 	WRITE_UNLOCK(&ip_nat_lock);
 
 	for (i = 0; i < ip_nat_htable_size; i++) {
net/ipv4/netfilter/ip_nat_proto_icmp.c +1 -1
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c
@@ -104,7 +104,7 @@
 }
 
 struct ip_nat_protocol ip_nat_protocol_icmp
-= { { NULL, NULL }, "ICMP", IPPROTO_ICMP,
+= { "ICMP", IPPROTO_ICMP,
     icmp_manip_pkt,
     icmp_in_range,
     icmp_unique_tuple,
net/ipv4/netfilter/ip_nat_proto_tcp.c +1 -1
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
@@ -162,7 +162,7 @@
 }
 
 struct ip_nat_protocol ip_nat_protocol_tcp
-= { { NULL, NULL }, "TCP", IPPROTO_TCP,
+= { "TCP", IPPROTO_TCP,
     tcp_manip_pkt,
     tcp_in_range,
     tcp_unique_tuple,
net/ipv4/netfilter/ip_nat_proto_udp.c +1 -1
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
@@ -148,7 +148,7 @@
 }
 
 struct ip_nat_protocol ip_nat_protocol_udp
-= { { NULL, NULL }, "UDP", IPPROTO_UDP,
+= { "UDP", IPPROTO_UDP,
     udp_manip_pkt,
     udp_in_range,
     udp_unique_tuple,
net/ipv4/netfilter/ip_nat_proto_unknown.c +2 -2
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c
@@ -60,8 +60,8 @@
 	return 0;
 }
 
-struct ip_nat_protocol unknown_nat_protocol = {
-	{ NULL, NULL }, "unknown", 0,
+struct ip_nat_protocol ip_nat_unknown_protocol = {
+	"unknown", 0,
 	unknown_manip_pkt,
 	unknown_in_range,
 	unknown_unique_tuple,
net/ipv4/netfilter/ip_nat_standalone.c +5 -10
diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -283,18 +283,13 @@
 int ip_nat_protocol_register(struct ip_nat_protocol *proto)
 {
 	int ret = 0;
-	struct list_head *i;
 
 	WRITE_LOCK(&ip_nat_lock);
-	list_for_each(i, &protos) {
-		if (((struct ip_nat_protocol *)i)->protonum
-		    == proto->protonum) {
-			ret = -EBUSY;
-			goto out;
-		}
+	if (ip_nat_protos[proto->protonum] != &ip_nat_unknown_protocol) {
+		ret = -EBUSY;
+		goto out;
 	}
-
-	list_prepend(&protos, proto);
+	ip_nat_protos[proto->protonum] = proto;
  out:
 	WRITE_UNLOCK(&ip_nat_lock);
 	return ret;
@@ -304,7 +299,7 @@
 void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
 {
 	WRITE_LOCK(&ip_nat_lock);
-	LIST_DELETE(&protos, proto);
+	ip_nat_protos[proto->protonum] = &ip_nat_unknown_protocol;
 	WRITE_UNLOCK(&ip_nat_lock);
 
 	/* Someone could be still looking at the proto in a bh. */