aboutsummaryrefslogtreecommitdiffstats
path: root/net/mpls/af_mpls.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-01-28 10:33:06 -0500
committerDavid S. Miller <davem@davemloft.net>2017-01-28 10:33:06 -0500
commit4e8f2fc1a55d543717efb70e170b09e773d0542b (patch)
tree30df1d7fc9dfa24fe2916711a17656682c3f7ec9 /net/mpls/af_mpls.c
parent158f323b9868b59967ad96957c4ca388161be321 (diff)
parent1b1bc42c1692e9b62756323c675a44cb1a1f9dbd (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Two trivial overlapping changes conflicts in MPLS and mlx5. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mpls/af_mpls.c')
-rw-r--r--net/mpls/af_mpls.c48
1 files changed, 25 insertions, 23 deletions
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 4dc81963af8f..64d3bf269a26 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -119,18 +119,19 @@ void mpls_stats_inc_outucastpkts(struct net_device *dev,
119} 119}
120EXPORT_SYMBOL_GPL(mpls_stats_inc_outucastpkts); 120EXPORT_SYMBOL_GPL(mpls_stats_inc_outucastpkts);
121 121
122static u32 mpls_multipath_hash(struct mpls_route *rt, 122static u32 mpls_multipath_hash(struct mpls_route *rt, struct sk_buff *skb)
123 struct sk_buff *skb, bool bos)
124{ 123{
125 struct mpls_entry_decoded dec; 124 struct mpls_entry_decoded dec;
125 unsigned int mpls_hdr_len = 0;
126 struct mpls_shim_hdr *hdr; 126 struct mpls_shim_hdr *hdr;
127 bool eli_seen = false; 127 bool eli_seen = false;
128 int label_index; 128 int label_index;
129 u32 hash = 0; 129 u32 hash = 0;
130 130
131 for (label_index = 0; label_index < MAX_MP_SELECT_LABELS && !bos; 131 for (label_index = 0; label_index < MAX_MP_SELECT_LABELS;
132 label_index++) { 132 label_index++) {
133 if (!pskb_may_pull(skb, sizeof(*hdr) * label_index)) 133 mpls_hdr_len += sizeof(*hdr);
134 if (!pskb_may_pull(skb, mpls_hdr_len))
134 break; 135 break;
135 136
136 /* Read and decode the current label */ 137 /* Read and decode the current label */
@@ -155,37 +156,38 @@ static u32 mpls_multipath_hash(struct mpls_route *rt,
155 eli_seen = true; 156 eli_seen = true;
156 } 157 }
157 158
158 bos = dec.bos; 159 if (!dec.bos)
159 if (bos && pskb_may_pull(skb, sizeof(*hdr) * label_index + 160 continue;
160 sizeof(struct iphdr))) { 161
162 /* found bottom label; does skb have room for a header? */
163 if (pskb_may_pull(skb, mpls_hdr_len + sizeof(struct iphdr))) {
161 const struct iphdr *v4hdr; 164 const struct iphdr *v4hdr;
162 165
163 v4hdr = (const struct iphdr *)(mpls_hdr(skb) + 166 v4hdr = (const struct iphdr *)(hdr + 1);
164 label_index);
165 if (v4hdr->version == 4) { 167 if (v4hdr->version == 4) {
166 hash = jhash_3words(ntohl(v4hdr->saddr), 168 hash = jhash_3words(ntohl(v4hdr->saddr),
167 ntohl(v4hdr->daddr), 169 ntohl(v4hdr->daddr),
168 v4hdr->protocol, hash); 170 v4hdr->protocol, hash);
169 } else if (v4hdr->version == 6 && 171 } else if (v4hdr->version == 6 &&
170 pskb_may_pull(skb, sizeof(*hdr) * label_index + 172 pskb_may_pull(skb, mpls_hdr_len +
171 sizeof(struct ipv6hdr))) { 173 sizeof(struct ipv6hdr))) {
172 const struct ipv6hdr *v6hdr; 174 const struct ipv6hdr *v6hdr;
173 175
174 v6hdr = (const struct ipv6hdr *)(mpls_hdr(skb) + 176 v6hdr = (const struct ipv6hdr *)(hdr + 1);
175 label_index);
176
177 hash = __ipv6_addr_jhash(&v6hdr->saddr, hash); 177 hash = __ipv6_addr_jhash(&v6hdr->saddr, hash);
178 hash = __ipv6_addr_jhash(&v6hdr->daddr, hash); 178 hash = __ipv6_addr_jhash(&v6hdr->daddr, hash);
179 hash = jhash_1word(v6hdr->nexthdr, hash); 179 hash = jhash_1word(v6hdr->nexthdr, hash);
180 } 180 }
181 } 181 }
182
183 break;
182 } 184 }
183 185
184 return hash; 186 return hash;
185} 187}
186 188
187static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt, 189static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt,
188 struct sk_buff *skb, bool bos) 190 struct sk_buff *skb)
189{ 191{
190 int alive = ACCESS_ONCE(rt->rt_nhn_alive); 192 int alive = ACCESS_ONCE(rt->rt_nhn_alive);
191 u32 hash = 0; 193 u32 hash = 0;
@@ -201,7 +203,7 @@ static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt,
201 if (alive <= 0) 203 if (alive <= 0)
202 return NULL; 204 return NULL;
203 205
204 hash = mpls_multipath_hash(rt, skb, bos); 206 hash = mpls_multipath_hash(rt, skb);
205 nh_index = hash % alive; 207 nh_index = hash % alive;
206 if (alive == rt->rt_nhn) 208 if (alive == rt->rt_nhn)
207 goto out; 209 goto out;
@@ -308,22 +310,22 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
308 hdr = mpls_hdr(skb); 310 hdr = mpls_hdr(skb);
309 dec = mpls_entry_decode(hdr); 311 dec = mpls_entry_decode(hdr);
310 312
311 /* Pop the label */
312 skb_pull(skb, sizeof(*hdr));
313 skb_reset_network_header(skb);
314
315 skb_orphan(skb);
316
317 rt = mpls_route_input_rcu(net, dec.label); 313 rt = mpls_route_input_rcu(net, dec.label);
318 if (!rt) { 314 if (!rt) {
319 MPLS_INC_STATS(mdev, rx_noroute); 315 MPLS_INC_STATS(mdev, rx_noroute);
320 goto drop; 316 goto drop;
321 } 317 }
322 318
323 nh = mpls_select_multipath(rt, skb, dec.bos); 319 nh = mpls_select_multipath(rt, skb);
324 if (!nh) 320 if (!nh)
325 goto err; 321 goto err;
326 322
323 /* Pop the label */
324 skb_pull(skb, sizeof(*hdr));
325 skb_reset_network_header(skb);
326
327 skb_orphan(skb);
328
327 if (skb_warn_if_lro(skb)) 329 if (skb_warn_if_lro(skb))
328 goto err; 330 goto err;
329 331