Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nf_conntrack: don't always initialize ct->proto

ct->proto is big(60 bytes) due to structure ip_ct_tcp, and we don't need
to initialize the whole for all the other protocols. This patch moves
proto to the end of structure nf_conn, and pushes the initialization down
to the individual protocols.

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>

authored by

Changli Gao and committed by
Patrick McHardy
e5fc9e7a c7537967

+13 -15
+3 -3
include/net/netfilter/nf_conntrack.h
··· 116 116 u_int32_t secmark; 117 117 #endif 118 118 119 - /* Storage reserved for other modules: */ 120 - union nf_conntrack_proto proto; 121 - 122 119 /* Extensions */ 123 120 struct nf_ct_ext *ext; 124 121 #ifdef CONFIG_NET_NS 125 122 struct net *ct_net; 126 123 #endif 124 + 125 + /* Storage reserved for other modules, must be the last member */ 126 + union nf_conntrack_proto proto; 127 127 }; 128 128 129 129 static inline struct nf_conn *
+2 -1
net/netfilter/nf_conntrack_core.c
··· 651 651 * and ct->tuplehash[IP_CT_DIR_REPLY].hnnode.next unchanged. 652 652 */ 653 653 memset(&ct->tuplehash[IP_CT_DIR_MAX], 0, 654 - sizeof(*ct) - offsetof(struct nf_conn, tuplehash[IP_CT_DIR_MAX])); 654 + offsetof(struct nf_conn, proto) - 655 + offsetof(struct nf_conn, tuplehash[IP_CT_DIR_MAX])); 655 656 spin_lock_init(&ct->lock); 656 657 ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; 657 658 ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL;
+1
net/netfilter/nf_conntrack_netlink.c
··· 1375 1375 } 1376 1376 #endif 1377 1377 1378 + memset(&ct->proto, 0, sizeof(ct->proto)); 1378 1379 if (cda[CTA_PROTOINFO]) { 1379 1380 err = ctnetlink_change_protoinfo(ct, cda); 1380 1381 if (err < 0)
+3
net/netfilter/nf_conntrack_proto_dccp.c
··· 452 452 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT; 453 453 ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER; 454 454 ct->proto.dccp.state = CT_DCCP_NONE; 455 + ct->proto.dccp.last_pkt = DCCP_PKT_REQUEST; 456 + ct->proto.dccp.last_dir = IP_CT_DIR_ORIGINAL; 457 + ct->proto.dccp.handshake_seq = 0; 455 458 return true; 456 459 457 460 out_invalid:
+1
net/netfilter/nf_conntrack_proto_sctp.c
··· 413 413 test_bit(SCTP_CID_COOKIE_ACK, map)) 414 414 return false; 415 415 416 + memset(&ct->proto.sctp, 0, sizeof(ct->proto.sctp)); 416 417 new_state = SCTP_CONNTRACK_MAX; 417 418 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) { 418 419 /* Don't need lock here: this conntrack not in circulation yet */
+3 -11
net/netfilter/nf_conntrack_proto_tcp.c
··· 1066 1066 BUG_ON(th == NULL); 1067 1067 1068 1068 /* Don't need lock here: this conntrack not in circulation yet */ 1069 - new_state 1070 - = tcp_conntracks[0][get_conntrack_index(th)] 1071 - [TCP_CONNTRACK_NONE]; 1069 + new_state = tcp_conntracks[0][get_conntrack_index(th)][TCP_CONNTRACK_NONE]; 1072 1070 1073 1071 /* Invalid: delete conntrack */ 1074 1072 if (new_state >= TCP_CONNTRACK_MAX) { ··· 1075 1077 } 1076 1078 1077 1079 if (new_state == TCP_CONNTRACK_SYN_SENT) { 1080 + memset(&ct->proto.tcp, 0, sizeof(ct->proto.tcp)); 1078 1081 /* SYN packet */ 1079 1082 ct->proto.tcp.seen[0].td_end = 1080 1083 segment_seq_plus_len(ntohl(th->seq), skb->len, ··· 1087 1088 ct->proto.tcp.seen[0].td_end; 1088 1089 1089 1090 tcp_options(skb, dataoff, th, &ct->proto.tcp.seen[0]); 1090 - ct->proto.tcp.seen[1].flags = 0; 1091 1091 } else if (nf_ct_tcp_loose == 0) { 1092 1092 /* Don't try to pick up connections. */ 1093 1093 return false; 1094 1094 } else { 1095 + memset(&ct->proto.tcp, 0, sizeof(ct->proto.tcp)); 1095 1096 /* 1096 1097 * We are in the middle of a connection, 1097 1098 * its history is lost for us. ··· 1106 1107 ct->proto.tcp.seen[0].td_maxend = 1107 1108 ct->proto.tcp.seen[0].td_end + 1108 1109 ct->proto.tcp.seen[0].td_maxwin; 1109 - ct->proto.tcp.seen[0].td_scale = 0; 1110 1110 1111 1111 /* We assume SACK and liberal window checking to handle 1112 1112 * window scaling */ ··· 1114 1116 IP_CT_TCP_FLAG_BE_LIBERAL; 1115 1117 } 1116 1118 1117 - ct->proto.tcp.seen[1].td_end = 0; 1118 - ct->proto.tcp.seen[1].td_maxend = 0; 1119 - ct->proto.tcp.seen[1].td_maxwin = 0; 1120 - ct->proto.tcp.seen[1].td_scale = 0; 1121 - 1122 1119 /* tcp_packet will set them */ 1123 - ct->proto.tcp.state = TCP_CONNTRACK_NONE; 1124 1120 ct->proto.tcp.last_index = TCP_NONE_SET; 1125 1121 1126 1122 pr_debug("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "