~james-page/ubuntu/saucy/openvswitch/1.12-snapshot

« back to all changes in this revision

Viewing changes to datapath/tunnel.c

  • Committer: James Page
  • Date: 2013-08-21 10:16:57 UTC
  • mfrom: (1.1.20)
  • Revision ID: james.page@canonical.com-20130821101657-3o0z0qeiv5zkwlzi
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
#include "vlan.h"
38
38
#include "vport.h"
39
39
 
40
 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
41
 
#define rt_dst(rt) (rt->dst)
42
 
#else
43
 
#define rt_dst(rt) (rt->u.dst)
44
 
#endif
45
 
 
46
40
/**
47
41
 *      ovs_tnl_rcv - ingress point for generic tunnel code
48
42
 *
58
52
 * - skb->csum does not include the inner Ethernet header.
59
53
 * - The layer pointers are undefined.
60
54
 */
61
 
void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb)
 
55
void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb,
 
56
                 struct ovs_key_ipv4_tunnel *tun_key)
62
57
{
63
58
        struct ethhdr *eh;
64
59
 
65
60
        skb_reset_mac_header(skb);
66
61
        eh = eth_hdr(skb);
67
62
 
68
 
        if (likely(ntohs(eh->h_proto) >= 1536))
 
63
        if (likely(ntohs(eh->h_proto) >= ETH_P_802_3_MIN))
69
64
                skb->protocol = eh->h_proto;
70
65
        else
71
66
                skb->protocol = htons(ETH_P_802_2);
81
76
                return;
82
77
        }
83
78
 
84
 
        ovs_vport_receive(vport, skb);
 
79
        ovs_vport_receive(vport, skb, tun_key);
85
80
}
86
81
 
87
 
static struct rtable *find_route(struct net *net,
88
 
                __be32 *saddr, __be32 daddr, u8 ipproto,
89
 
                u8 tos, u32 skb_mark)
 
82
struct rtable *find_route(struct net *net,
 
83
                          __be32 *saddr, __be32 daddr, u8 ipproto,
 
84
                          u8 tos, u32 skb_mark)
90
85
{
91
86
        struct rtable *rt;
92
87
        /* Tunnel configuration keeps DSCP part of TOS bits, But Linux
141
136
        return false;
142
137
}
143
138
 
144
 
static struct sk_buff *handle_offloads(struct sk_buff *skb,
145
 
                                       const struct rtable *rt,
146
 
                                       int tunnel_hlen)
 
139
static struct sk_buff *handle_offloads(struct sk_buff *skb)
147
140
{
148
 
        int min_headroom;
149
141
        int err;
150
142
 
151
 
        min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len
152
 
                        + tunnel_hlen
153
 
                        + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);
154
 
 
155
 
        if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
156
 
                int head_delta = SKB_DATA_ALIGN(min_headroom -
157
 
                                                skb_headroom(skb) +
158
 
                                                16);
159
 
                err = pskb_expand_head(skb, max_t(int, head_delta, 0),
160
 
                                        0, GFP_ATOMIC);
161
 
                if (unlikely(err))
162
 
                        goto error_free;
163
 
        }
164
 
 
165
143
        forward_ip_summed(skb, true);
166
144
 
167
145
        if (skb_is_gso(skb)) {
168
146
                struct sk_buff *nskb;
169
 
 
170
 
                nskb = skb_gso_segment(skb, 0);
 
147
                char cb[sizeof(skb->cb)];
 
148
 
 
149
                memcpy(cb, skb->cb, sizeof(cb));
 
150
 
 
151
                nskb = __skb_gso_segment(skb, 0, false);
171
152
                if (IS_ERR(nskb)) {
172
 
                        kfree_skb(skb);
173
153
                        err = PTR_ERR(nskb);
174
154
                        goto error;
175
155
                }
176
156
 
177
157
                consume_skb(skb);
178
158
                skb = nskb;
 
159
                while (nskb) {
 
160
                        memcpy(nskb->cb, cb, sizeof(cb));
 
161
                        nskb = nskb->next;
 
162
                }
179
163
        } else if (get_ip_summed(skb) == OVS_CSUM_PARTIAL) {
180
164
                /* Pages aren't locked and could change at any time.
181
165
                 * If this happens after we compute the checksum, the
185
169
                if (unlikely(need_linearize(skb))) {
186
170
                        err = __skb_linearize(skb);
187
171
                        if (unlikely(err))
188
 
                                goto error_free;
 
172
                                goto error;
189
173
                }
190
174
 
191
175
                err = skb_checksum_help(skb);
192
176
                if (unlikely(err))
193
 
                        goto error_free;
 
177
                        goto error;
194
178
        }
195
179
 
196
180
        set_ip_summed(skb, OVS_CSUM_NONE);
197
181
 
198
182
        return skb;
199
183
 
200
 
error_free:
201
 
        kfree_skb(skb);
202
184
error:
203
185
        return ERR_PTR(err);
204
186
}
211
193
        int low;
212
194
        int high;
213
195
        unsigned int range;
214
 
        u32 hash = OVS_CB(skb)->flow->hash;
 
196
        struct sw_flow_key *pkt_key = OVS_CB(skb)->pkt_key;
 
197
        u32 hash = jhash2((const u32 *)pkt_key,
 
198
                          sizeof(*pkt_key) / sizeof(u32), 0);
215
199
 
216
200
        inet_get_local_port_range(&low, &high);
217
201
        range = (high - low) + 1;
218
202
        return (((u64) hash * range) >> 32) + low;
219
203
}
220
204
 
221
 
int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
 
205
int ovs_tnl_send(struct vport *vport, struct sk_buff *skb,
 
206
                 u8 ipproto, int tunnel_hlen,
 
207
                 void (*build_header)(const struct vport *,
 
208
                                      struct sk_buff *,
 
209
                                      int tunnel_hlen))
222
210
{
223
 
        struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
 
211
        int min_headroom;
224
212
        struct rtable *rt;
225
213
        __be32 saddr;
226
214
        int sent_len = 0;
227
 
        int tunnel_hlen;
228
 
 
229
 
        if (unlikely(!OVS_CB(skb)->tun_key))
230
 
                goto error_free;
 
215
        int err;
 
216
        struct sk_buff *nskb;
231
217
 
232
218
        /* Route lookup */
233
219
        saddr = OVS_CB(skb)->tun_key->ipv4_src;
234
220
        rt = find_route(ovs_dp_get_net(vport->dp),
235
221
                        &saddr,
236
222
                        OVS_CB(skb)->tun_key->ipv4_dst,
237
 
                        tnl_vport->tnl_ops->ipproto,
 
223
                        ipproto,
238
224
                        OVS_CB(skb)->tun_key->ipv4_tos,
239
225
                        skb_get_mark(skb));
240
 
        if (IS_ERR(rt))
241
 
                goto error_free;
 
226
        if (IS_ERR(rt)) {
 
227
                err = PTR_ERR(rt);
 
228
                goto error;
 
229
        }
 
230
 
 
231
        tunnel_hlen += sizeof(struct iphdr);
 
232
 
 
233
        min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len
 
234
                        + tunnel_hlen
 
235
                        + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);
 
236
 
 
237
        if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
 
238
                int head_delta = SKB_DATA_ALIGN(min_headroom -
 
239
                                                skb_headroom(skb) +
 
240
                                                16);
 
241
 
 
242
                err = pskb_expand_head(skb, max_t(int, head_delta, 0),
 
243
                                        0, GFP_ATOMIC);
 
244
                if (unlikely(err))
 
245
                        goto err_free_rt;
 
246
        }
242
247
 
243
248
        /* Offloading */
244
 
        tunnel_hlen = tnl_vport->tnl_ops->hdr_len(OVS_CB(skb)->tun_key);
245
 
        tunnel_hlen += sizeof(struct iphdr);
246
 
 
247
 
        skb = handle_offloads(skb, rt, tunnel_hlen);
248
 
        if (IS_ERR(skb)) {
249
 
                skb = NULL;
 
249
        nskb = handle_offloads(skb);
 
250
        if (IS_ERR(nskb)) {
 
251
                err = PTR_ERR(nskb);
250
252
                goto err_free_rt;
251
253
        }
 
254
        skb = nskb;
252
255
 
253
256
        /* Reset SKB */
254
257
        nf_reset(skb);
260
263
                struct sk_buff *next_skb = skb->next;
261
264
                struct iphdr *iph;
262
265
                int frag_len;
263
 
                int err;
264
266
 
265
267
                skb->next = NULL;
266
268
 
278
280
                        skb_dst_set(skb, &rt_dst(rt));
279
281
 
280
282
                /* Push Tunnel header. */
281
 
                tnl_vport->tnl_ops->build_header(vport, skb, tunnel_hlen);
 
283
                build_header(vport, skb, tunnel_hlen);
282
284
 
283
285
                /* Push IP header. */
284
286
                iph = ip_hdr(skb);
285
287
                iph->version    = 4;
286
288
                iph->ihl        = sizeof(struct iphdr) >> 2;
287
 
                iph->protocol   = tnl_vport->tnl_ops->ipproto;
 
289
                iph->protocol   = ipproto;
288
290
                iph->daddr      = OVS_CB(skb)->tun_key->ipv4_dst;
289
291
                iph->saddr      = saddr;
290
292
                iph->tos        = OVS_CB(skb)->tun_key->ipv4_tos;
291
293
                iph->ttl        = OVS_CB(skb)->tun_key->ipv4_ttl;
292
294
                iph->frag_off   = OVS_CB(skb)->tun_key->tun_flags &
293
 
                                  OVS_TNL_F_DONT_FRAGMENT ?  htons(IP_DF) : 0;
 
295
                                  TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
294
296
                /*
295
297
                 * Allow our local IP stack to fragment the outer packet even
296
298
                 * if the DF bit is set as a last resort.  We also need to
313
315
                skb = next_skb;
314
316
        }
315
317
 
316
 
        if (unlikely(sent_len == 0))
317
 
                ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
318
 
 
319
318
        return sent_len;
320
319
 
321
320
err_free_rt:
322
321
        ip_rt_put(rt);
323
 
error_free:
324
 
        kfree_skb(skb);
325
 
        ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
326
 
        return sent_len;
327
 
}
328
 
 
329
 
struct vport *ovs_tnl_create(const struct vport_parms *parms,
330
 
                             const struct vport_ops *vport_ops,
331
 
                             const struct tnl_ops *tnl_ops)
332
 
{
333
 
        struct vport *vport;
334
 
        struct tnl_vport *tnl_vport;
335
 
        int err;
336
 
 
337
 
        vport = ovs_vport_alloc(sizeof(struct tnl_vport), vport_ops, parms);
338
 
        if (IS_ERR(vport)) {
339
 
                err = PTR_ERR(vport);
340
 
                goto error;
341
 
        }
342
 
 
343
 
        tnl_vport = tnl_vport_priv(vport);
344
 
 
345
 
        strcpy(tnl_vport->name, parms->name);
346
 
        tnl_vport->tnl_ops = tnl_ops;
347
 
 
348
 
        return vport;
349
 
 
350
322
error:
351
 
        return ERR_PTR(err);
352
 
}
353
 
 
354
 
static void free_port_rcu(struct rcu_head *rcu)
355
 
{
356
 
        struct tnl_vport *tnl_vport = container_of(rcu,
357
 
                                                   struct tnl_vport, rcu);
358
 
 
359
 
        ovs_vport_free(vport_from_priv(tnl_vport));
360
 
}
361
 
 
362
 
void ovs_tnl_destroy(struct vport *vport)
363
 
{
364
 
        struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
365
 
 
366
 
        call_rcu(&tnl_vport->rcu, free_port_rcu);
367
 
}
368
 
 
369
 
const char *ovs_tnl_get_name(const struct vport *vport)
370
 
{
371
 
        const struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
372
 
        return tnl_vport->name;
 
323
        return err;
373
324
}