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

« back to all changes in this revision

Viewing changes to lib/odp-execute.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:
 
1
/*
 
2
 * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
 
3
 * Copyright (c) 2013 Simon Horman
 
4
 *
 
5
 * Licensed under the Apache License, Version 2.0 (the "License");
 
6
 * you may not use this file except in compliance with the License.
 
7
 * You may obtain a copy of the License at:
 
8
 *
 
9
 *     http://www.apache.org/licenses/LICENSE-2.0
 
10
 *
 
11
 * Unless required by applicable law or agreed to in writing, software
 
12
 * distributed under the License is distributed on an "AS IS" BASIS,
 
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
 * See the License for the specific language governing permissions and
 
15
 * limitations under the License.
 
16
 */
 
17
 
 
18
#include <config.h>
 
19
#include "odp-execute.h"
 
20
#include <linux/openvswitch.h>
 
21
#include <stdlib.h>
 
22
#include <string.h>
 
23
 
 
24
#include "netlink.h"
 
25
#include "ofpbuf.h"
 
26
#include "odp-util.h"
 
27
#include "packets.h"
 
28
#include "util.h"
 
29
 
 
30
static void
 
31
odp_eth_set_addrs(struct ofpbuf *packet, const struct ovs_key_ethernet *eth_key)
 
32
{
 
33
    struct eth_header *eh = packet->l2;
 
34
 
 
35
    memcpy(eh->eth_src, eth_key->eth_src, sizeof eh->eth_src);
 
36
    memcpy(eh->eth_dst, eth_key->eth_dst, sizeof eh->eth_dst);
 
37
}
 
38
 
 
39
static void
 
40
odp_set_tunnel_action(const struct nlattr *a, struct flow_tnl *tun_key)
 
41
{
 
42
    enum odp_key_fitness fitness;
 
43
 
 
44
    fitness = odp_tun_key_from_attr(a, tun_key);
 
45
    ovs_assert(fitness != ODP_FIT_ERROR);
 
46
}
 
47
 
 
48
static void
 
49
odp_execute_set_action(struct ofpbuf *packet, const struct nlattr *a,
 
50
                       struct flow *flow)
 
51
{
 
52
    enum ovs_key_attr type = nl_attr_type(a);
 
53
    const struct ovs_key_ipv4 *ipv4_key;
 
54
    const struct ovs_key_ipv6 *ipv6_key;
 
55
    const struct ovs_key_tcp *tcp_key;
 
56
    const struct ovs_key_udp *udp_key;
 
57
 
 
58
    switch (type) {
 
59
    case OVS_KEY_ATTR_PRIORITY:
 
60
        flow->skb_priority = nl_attr_get_u32(a);
 
61
        break;
 
62
 
 
63
    case OVS_KEY_ATTR_TUNNEL:
 
64
        odp_set_tunnel_action(a, &flow->tunnel);
 
65
        break;
 
66
 
 
67
    case OVS_KEY_ATTR_SKB_MARK:
 
68
        flow->skb_mark = nl_attr_get_u32(a);
 
69
        break;
 
70
 
 
71
    case OVS_KEY_ATTR_ETHERNET:
 
72
        odp_eth_set_addrs(packet,
 
73
                          nl_attr_get_unspec(a, sizeof(struct ovs_key_ethernet)));
 
74
        break;
 
75
 
 
76
    case OVS_KEY_ATTR_IPV4:
 
77
        ipv4_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv4));
 
78
        packet_set_ipv4(packet, ipv4_key->ipv4_src, ipv4_key->ipv4_dst,
 
79
                        ipv4_key->ipv4_tos, ipv4_key->ipv4_ttl);
 
80
        break;
 
81
 
 
82
    case OVS_KEY_ATTR_IPV6:
 
83
        ipv6_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv6));
 
84
        packet_set_ipv6(packet, ipv6_key->ipv6_proto, ipv6_key->ipv6_src,
 
85
                        ipv6_key->ipv6_dst, ipv6_key->ipv6_tclass,
 
86
                        ipv6_key->ipv6_label, ipv6_key->ipv6_hlimit);
 
87
        break;
 
88
 
 
89
    case OVS_KEY_ATTR_TCP:
 
90
        tcp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_tcp));
 
91
        packet_set_tcp_port(packet, tcp_key->tcp_src, tcp_key->tcp_dst);
 
92
        break;
 
93
 
 
94
    case OVS_KEY_ATTR_UDP:
 
95
        udp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_udp));
 
96
        packet_set_udp_port(packet, udp_key->udp_src, udp_key->udp_dst);
 
97
        break;
 
98
 
 
99
    case OVS_KEY_ATTR_MPLS:
 
100
         set_mpls_lse(packet, nl_attr_get_be32(a));
 
101
         break;
 
102
 
 
103
    case OVS_KEY_ATTR_UNSPEC:
 
104
    case OVS_KEY_ATTR_ENCAP:
 
105
    case OVS_KEY_ATTR_ETHERTYPE:
 
106
    case OVS_KEY_ATTR_IN_PORT:
 
107
    case OVS_KEY_ATTR_VLAN:
 
108
    case OVS_KEY_ATTR_ICMP:
 
109
    case OVS_KEY_ATTR_ICMPV6:
 
110
    case OVS_KEY_ATTR_ARP:
 
111
    case OVS_KEY_ATTR_ND:
 
112
    case __OVS_KEY_ATTR_MAX:
 
113
    default:
 
114
        NOT_REACHED();
 
115
    }
 
116
}
 
117
 
 
118
static void
 
119
odp_execute_sample(void *dp, struct ofpbuf *packet, struct flow *key,
 
120
                   const struct nlattr *action,
 
121
                   void (*output)(void *dp, struct ofpbuf *packet,
 
122
                                  uint32_t out_port),
 
123
                   void (*userspace)(void *dp, struct ofpbuf *packet,
 
124
                                     const struct flow *key,
 
125
                                     const struct nlattr *a))
 
126
{
 
127
    const struct nlattr *subactions = NULL;
 
128
    const struct nlattr *a;
 
129
    size_t left;
 
130
 
 
131
    NL_NESTED_FOR_EACH_UNSAFE (a, left, action) {
 
132
        int type = nl_attr_type(a);
 
133
 
 
134
        switch ((enum ovs_sample_attr) type) {
 
135
        case OVS_SAMPLE_ATTR_PROBABILITY:
 
136
            if (random_uint32() >= nl_attr_get_u32(a)) {
 
137
                return;
 
138
            }
 
139
            break;
 
140
 
 
141
        case OVS_SAMPLE_ATTR_ACTIONS:
 
142
            subactions = a;
 
143
            break;
 
144
 
 
145
        case OVS_SAMPLE_ATTR_UNSPEC:
 
146
        case __OVS_SAMPLE_ATTR_MAX:
 
147
        default:
 
148
            NOT_REACHED();
 
149
        }
 
150
    }
 
151
 
 
152
    odp_execute_actions(dp, packet, key, nl_attr_get(subactions),
 
153
                        nl_attr_get_size(subactions), output, userspace);
 
154
}
 
155
 
 
156
void
 
157
odp_execute_actions(void *dp, struct ofpbuf *packet, struct flow *key,
 
158
                    const struct nlattr *actions, size_t actions_len,
 
159
                    void (*output)(void *dp, struct ofpbuf *packet,
 
160
                                   uint32_t out_port),
 
161
                    void (*userspace)(void *dp, struct ofpbuf *packet,
 
162
                                      const struct flow *key,
 
163
                                      const struct nlattr *a))
 
164
{
 
165
    const struct nlattr *a;
 
166
    unsigned int left;
 
167
 
 
168
    NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) {
 
169
        int type = nl_attr_type(a);
 
170
 
 
171
        switch ((enum ovs_action_attr) type) {
 
172
        case OVS_ACTION_ATTR_OUTPUT:
 
173
            if (output) {
 
174
                output(dp, packet, nl_attr_get_u32(a));
 
175
            }
 
176
            break;
 
177
 
 
178
        case OVS_ACTION_ATTR_USERSPACE: {
 
179
            const struct nlattr *userdata;
 
180
 
 
181
            userdata = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA);
 
182
            userspace(dp, packet, key, userdata);
 
183
            break;
 
184
        }
 
185
 
 
186
        case OVS_ACTION_ATTR_PUSH_VLAN: {
 
187
            const struct ovs_action_push_vlan *vlan = nl_attr_get(a);
 
188
            eth_push_vlan(packet, vlan->vlan_tci);
 
189
            break;
 
190
        }
 
191
 
 
192
        case OVS_ACTION_ATTR_POP_VLAN:
 
193
            eth_pop_vlan(packet);
 
194
            break;
 
195
 
 
196
        case OVS_ACTION_ATTR_PUSH_MPLS: {
 
197
            const struct ovs_action_push_mpls *mpls = nl_attr_get(a);
 
198
            push_mpls(packet, mpls->mpls_ethertype, mpls->mpls_lse);
 
199
            break;
 
200
         }
 
201
 
 
202
        case OVS_ACTION_ATTR_POP_MPLS:
 
203
            pop_mpls(packet, nl_attr_get_be16(a));
 
204
            break;
 
205
 
 
206
        case OVS_ACTION_ATTR_SET:
 
207
            odp_execute_set_action(packet, nl_attr_get(a), key);
 
208
            break;
 
209
 
 
210
        case OVS_ACTION_ATTR_SAMPLE:
 
211
            odp_execute_sample(dp, packet, key, a, output, userspace);
 
212
            break;
 
213
 
 
214
        case OVS_ACTION_ATTR_UNSPEC:
 
215
        case __OVS_ACTION_ATTR_MAX:
 
216
            NOT_REACHED();
 
217
        }
 
218
    }
 
219
}