This patch addresses two issues: a) Fix usage of u32 and __be32 that causes endianess warnings via sparse. b) Ensure consistent hashing in a cluster that is composed of big and little endian systems. Thus, we obtain the same hash mark in an heterogeneous cluster.
Unified · Split
| @@ -27,7 +27,12 @@ union hmark_ports { · 26 unmodified lines | ||
| 27 | 27 | __u16 src; |
| 28 | 28 | __u16 dst; |
| 29 | 29 | } p16; |
| 30 | + struct { | |
| 31 | + __be16 src; | |
| 32 | + __be16 dst; | |
| 33 | + } b16; | |
| 30 | 34 | __u32 v32; |
| 35 | + __be32 b32; | |
| 31 | 36 | }; |
| 32 | 37 | |
| 33 | 38 | struct xt_hmark_info { |
| @@ -32,13 +32,13 @@ MODULE_ALIAS("ipt_HMARK"); · 31 unmodified lines | ||
| 32 | 32 | MODULE_ALIAS("ip6t_HMARK"); |
| 33 | 33 | |
| 34 | 34 | struct hmark_tuple { |
| 35 | − u32 src; | |
| 36 | − u32 dst; | |
| 35 | + __be32 src; | |
| 36 | + __be32 dst; | |
| 37 | 37 | union hmark_ports uports; |
| 38 | − uint8_t proto; | |
| 38 | + u8 proto; | |
| 39 | 39 | }; |
| 40 | 40 | |
| 41 | −static inline u32 hmark_addr6_mask(const __u32 *addr32, const __u32 *mask) | |
| 41 | +static inline __be32 hmark_addr6_mask(const __be32 *addr32, const __be32 *mask) | |
| 42 | 42 | { |
| 43 | 43 | return (addr32[0] & mask[0]) ^ |
| 44 | 44 | (addr32[1] & mask[1]) ^ |
| @@ -46,8 +46,8 @@ static inline u32 hmark_addr6_mask(const __u32 *addr32, const __u32 *mask) · 1 unmodified line | ||
| 46 | 46 | (addr32[3] & mask[3]); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | −static inline u32 | |
| 50 | −hmark_addr_mask(int l3num, const __u32 *addr32, const __u32 *mask) | |
| 49 | +static inline __be32 | |
| 50 | +hmark_addr_mask(int l3num, const __be32 *addr32, const __be32 *mask) | |
| 51 | 51 | { |
| 52 | 52 | switch (l3num) { |
| 53 | 53 | case AF_INET: |
| @@ -58,6 +58,22 @@ hmark_addr_mask(int l3num, const __u32 *addr32, const __u32 *mask) · 4 unmodified lines | ||
| 58 | 58 | return 0; |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | +static inline void hmark_swap_ports(union hmark_ports *uports, | |
| 62 | + const struct xt_hmark_info *info) | |
| 63 | +{ | |
| 64 | + union hmark_ports hp; | |
| 65 | + u16 src, dst; | |
| 66 | + | |
| 67 | + hp.b32 = (uports->b32 & info->port_mask.b32) | info->port_set.b32; | |
| 68 | + src = ntohs(hp.b16.src); | |
| 69 | + dst = ntohs(hp.b16.dst); | |
| 70 | + | |
| 71 | + if (dst > src) | |
| 72 | + uports->v32 = (dst << 16) | src; | |
| 73 | + else | |
| 74 | + uports->v32 = (src << 16) | dst; | |
| 75 | +} | |
| 76 | + | |
| 61 | 77 | static int |
| 62 | 78 | hmark_ct_set_htuple(const struct sk_buff *skb, struct hmark_tuple *t, |
| 63 | 79 | const struct xt_hmark_info *info) |
| @@ -74,22 +90,19 @@ hmark_ct_set_htuple(const struct sk_buff *skb, struct hmark_tuple *t, · 10 unmodified lines | ||
| 74 | 90 | otuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; |
| 75 | 91 | rtuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; |
| 76 | 92 | |
| 77 | − t->src = hmark_addr_mask(otuple->src.l3num, otuple->src.u3.all, | |
| 78 | − info->src_mask.all); | |
| 79 | − t->dst = hmark_addr_mask(otuple->src.l3num, rtuple->src.u3.all, | |
| 80 | − info->dst_mask.all); | |
| 93 | + t->src = hmark_addr_mask(otuple->src.l3num, otuple->src.u3.ip6, | |
| 94 | + info->src_mask.ip6); | |
| 95 | + t->dst = hmark_addr_mask(otuple->src.l3num, rtuple->src.u3.ip6, | |
| 96 | + info->dst_mask.ip6); | |
| 81 | 97 | |
| 82 | 98 | if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3)) |
| 83 | 99 | return 0; |
| 84 | 100 | |
| 85 | 101 | t->proto = nf_ct_protonum(ct); |
| 86 | 102 | if (t->proto != IPPROTO_ICMP) { |
| 87 | − t->uports.p16.src = otuple->src.u.all; | |
| 88 | − t->uports.p16.dst = rtuple->src.u.all; | |
| 89 | − t->uports.v32 = (t->uports.v32 & info->port_mask.v32) | | |
| 90 | − info->port_set.v32; | |
| 91 | − if (t->uports.p16.dst < t->uports.p16.src) | |
| 92 | − swap(t->uports.p16.dst, t->uports.p16.src); | |
| 103 | + t->uports.b16.src = otuple->src.u.all; | |
| 104 | + t->uports.b16.dst = rtuple->src.u.all; | |
| 105 | + hmark_swap_ports(&t->uports, info); | |
| 93 | 106 | } |
| 94 | 107 | |
| 95 | 108 | return 0; |
| @@ -98,15 +111,19 @@ hmark_ct_set_htuple(const struct sk_buff *skb, struct hmark_tuple *t, · 2 unmodified lines | ||
| 98 | 111 | #endif |
| 99 | 112 | } |
| 100 | 113 | |
| 114 | +/* This hash function is endian independent, to ensure consistent hashing if | |
| 115 | + * the cluster is composed of big and little endian systems. */ | |
| 101 | 116 | static inline u32 |
| 102 | 117 | hmark_hash(struct hmark_tuple *t, const struct xt_hmark_info *info) |
| 103 | 118 | { |
| 104 | 119 | u32 hash; |
| 120 | + u32 src = ntohl(t->src); | |
| 121 | + u32 dst = ntohl(t->dst); | |
| 105 | 122 | |
| 106 | − if (t->dst < t->src) | |
| 107 | − swap(t->src, t->dst); | |
| 123 | + if (dst < src) | |
| 124 | + swap(src, dst); | |
| 108 | 125 | |
| 109 | − hash = jhash_3words(t->src, t->dst, t->uports.v32, info->hashrnd); | |
| 126 | + hash = jhash_3words(src, dst, t->uports.v32, info->hashrnd); | |
| 110 | 127 | hash = hash ^ (t->proto & info->proto_mask); |
| 111 | 128 | |
| 112 | 129 | return (((u64)hash * info->hmodulus) >> 32) + info->hoffset; |
| @@ -126,11 +143,7 @@ hmark_set_tuple_ports(const struct sk_buff *skb, unsigned int nhoff, · 13 unmodified lines | ||
| 126 | 143 | if (skb_copy_bits(skb, nhoff, &t->uports, sizeof(t->uports)) < 0) |
| 127 | 144 | return; |
| 128 | 145 | |
| 129 | − t->uports.v32 = (t->uports.v32 & info->port_mask.v32) | | |
| 130 | − info->port_set.v32; | |
| 131 | − | |
| 132 | − if (t->uports.p16.dst < t->uports.p16.src) | |
| 133 | − swap(t->uports.p16.dst, t->uports.p16.src); | |
| 146 | + hmark_swap_ports(&t->uports, info); | |
| 134 | 147 | } |
| 135 | 148 | |
| 136 | 149 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
| @@ -178,8 +191,8 @@ hmark_pkt_set_htuple_ipv6(const struct sk_buff *skb, struct hmark_tuple *t, · 41 unmodified lines | ||
| 178 | 191 | return -1; |
| 179 | 192 | } |
| 180 | 193 | noicmp: |
| 181 | − t->src = hmark_addr6_mask(ip6->saddr.s6_addr32, info->src_mask.all); | |
| 182 | − t->dst = hmark_addr6_mask(ip6->daddr.s6_addr32, info->dst_mask.all); | |
| 194 | + t->src = hmark_addr6_mask(ip6->saddr.s6_addr32, info->src_mask.ip6); | |
| 195 | + t->dst = hmark_addr6_mask(ip6->daddr.s6_addr32, info->dst_mask.ip6); | |
| 183 | 196 | |
| 184 | 197 | if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3)) |
| 185 | 198 | return 0; |
| @@ -255,11 +268,8 @@ hmark_pkt_set_htuple_ipv4(const struct sk_buff *skb, struct hmark_tuple *t, · 69 unmodified lines | ||
| 255 | 268 | } |
| 256 | 269 | } |
| 257 | 270 | |
| 258 | − t->src = (__force u32) ip->saddr; | |
| 259 | − t->dst = (__force u32) ip->daddr; | |
| 260 | − | |
| 261 | − t->src &= info->src_mask.ip; | |
| 262 | − t->dst &= info->dst_mask.ip; | |
| 271 | + t->src = ip->saddr & info->src_mask.ip; | |
| 272 | + t->dst = ip->daddr & info->dst_mask.ip; | |
| 263 | 273 | |
| 264 | 274 | if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3)) |
| 265 | 275 | return 0; |