aboutsummaryrefslogtreecommitdiffstats
path: root/net/mpls/af_mpls.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2017-02-26 15:34:42 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2017-02-26 15:34:42 -0500
commit8e22e1b3499a446df48c2b26667ca36c55bf864c (patch)
tree5329f98b3eb3c95a9dcbab0fa4f9b6e62f0e788d /net/mpls/af_mpls.c
parent00d3c14f14d51babd8aeafd5fa734ccf04f5ca3d (diff)
parent64a577196d66b44e37384bc5c4d78c61f59d5b2a (diff)
Merge airlied/drm-next into drm-misc-next
Backmerge the main pull request to sync up with all the newly landed drivers. Otherwise we'll have chaos even before 4.12 started in earnest. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
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 15fe97644ffe..5b77377e5a15 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -98,18 +98,19 @@ bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu)
98} 98}
99EXPORT_SYMBOL_GPL(mpls_pkt_too_big); 99EXPORT_SYMBOL_GPL(mpls_pkt_too_big);
100 100
101static u32 mpls_multipath_hash(struct mpls_route *rt, 101static u32 mpls_multipath_hash(struct mpls_route *rt, struct sk_buff *skb)
102 struct sk_buff *skb, bool bos)
103{ 102{
104 struct mpls_entry_decoded dec; 103 struct mpls_entry_decoded dec;
104 unsigned int mpls_hdr_len = 0;
105 struct mpls_shim_hdr *hdr; 105 struct mpls_shim_hdr *hdr;
106 bool eli_seen = false; 106 bool eli_seen = false;
107 int label_index; 107 int label_index;
108 u32 hash = 0; 108 u32 hash = 0;
109 109
110 for (label_index = 0; label_index < MAX_MP_SELECT_LABELS && !bos; 110 for (label_index = 0; label_index < MAX_MP_SELECT_LABELS;
111 label_index++) { 111 label_index++) {
112 if (!pskb_may_pull(skb, sizeof(*hdr) * label_index)) 112 mpls_hdr_len += sizeof(*hdr);
113 if (!pskb_may_pull(skb, mpls_hdr_len))
113 break; 114 break;
114 115
115 /* Read and decode the current label */ 116 /* Read and decode the current label */
@@ -134,37 +135,38 @@ static u32 mpls_multipath_hash(struct mpls_route *rt,
134 eli_seen = true; 135 eli_seen = true;
135 } 136 }
136 137
137 bos = dec.bos; 138 if (!dec.bos)
138 if (bos && pskb_may_pull(skb, sizeof(*hdr) * label_index + 139 continue;
139 sizeof(struct iphdr))) { 140
141 /* found bottom label; does skb have room for a header? */
142 if (pskb_may_pull(skb, mpls_hdr_len + sizeof(struct iphdr))) {
140 const struct iphdr *v4hdr; 143 const struct iphdr *v4hdr;
141 144
142 v4hdr = (const struct iphdr *)(mpls_hdr(skb) + 145 v4hdr = (const struct iphdr *)(hdr + 1);
143 label_index);
144 if (v4hdr->version == 4) { 146 if (v4hdr->version == 4) {
145 hash = jhash_3words(ntohl(v4hdr->saddr), 147 hash = jhash_3words(ntohl(v4hdr->saddr),
146 ntohl(v4hdr->daddr), 148 ntohl(v4hdr->daddr),
147 v4hdr->protocol, hash); 149 v4hdr->protocol, hash);
148 } else if (v4hdr->version == 6 && 150 } else if (v4hdr->version == 6 &&
149 pskb_may_pull(skb, sizeof(*hdr) * label_index + 151 pskb_may_pull(skb, mpls_hdr_len +
150 sizeof(struct ipv6hdr))) { 152 sizeof(struct ipv6hdr))) {
151 const struct ipv6hdr *v6hdr; 153 const struct ipv6hdr *v6hdr;
152 154
153 v6hdr = (const struct ipv6hdr *)(mpls_hdr(skb) + 155 v6hdr = (const struct ipv6hdr *)(hdr + 1);
154 label_index);
155
156 hash = __ipv6_addr_jhash(&v6hdr->saddr, hash); 156 hash = __ipv6_addr_jhash(&v6hdr->saddr, hash);
157 hash = __ipv6_addr_jhash(&v6hdr->daddr, hash); 157 hash = __ipv6_addr_jhash(&v6hdr->daddr, hash);
158 hash = jhash_1word(v6hdr->nexthdr, hash); 158 hash = jhash_1word(v6hdr->nexthdr, hash);
159 } 159 }
160 } 160 }
161
162 break;
161 } 163 }
162 164
163 return hash; 165 return hash;
164} 166}
165 167
166static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt, 168static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt,
167 struct sk_buff *skb, bool bos) 169 struct sk_buff *skb)
168{ 170{
169 int alive = ACCESS_ONCE(rt->rt_nhn_alive); 171 int alive = ACCESS_ONCE(rt->rt_nhn_alive);
170 u32 hash = 0; 172 u32 hash = 0;
@@ -180,7 +182,7 @@ static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt,
180 if (alive <= 0) 182 if (alive <= 0)
181 return NULL; 183 return NULL;
182 184
183 hash = mpls_multipath_hash(rt, skb, bos); 185 hash = mpls_multipath_hash(rt, skb);
184 nh_index = hash % alive; 186 nh_index = hash % alive;
185 if (alive == rt->rt_nhn) 187 if (alive == rt->rt_nhn)
186 goto out; 188 goto out;
@@ -278,17 +280,11 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
278 hdr = mpls_hdr(skb); 280 hdr = mpls_hdr(skb);
279 dec = mpls_entry_decode(hdr); 281 dec = mpls_entry_decode(hdr);
280 282
281 /* Pop the label */
282 skb_pull(skb, sizeof(*hdr));
283 skb_reset_network_header(skb);
284
285 skb_orphan(skb);
286
287 rt = mpls_route_input_rcu(net, dec.label); 283 rt = mpls_route_input_rcu(net, dec.label);
288 if (!rt) 284 if (!rt)
289 goto drop; 285 goto drop;
290 286
291 nh = mpls_select_multipath(rt, skb, dec.bos); 287 nh = mpls_select_multipath(rt, skb);
292 if (!nh) 288 if (!nh)
293 goto drop; 289 goto drop;
294 290
@@ -297,6 +293,12 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
297 if (!mpls_output_possible(out_dev)) 293 if (!mpls_output_possible(out_dev))
298 goto drop; 294 goto drop;
299 295
296 /* Pop the label */
297 skb_pull(skb, sizeof(*hdr));
298 skb_reset_network_header(skb);
299
300 skb_orphan(skb);
301
300 if (skb_warn_if_lro(skb)) 302 if (skb_warn_if_lro(skb))
301 goto drop; 303 goto drop;
302 304