1 /* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
4 * We are making the OpenFlow specification and associated documentation
5 * (Software) available for public use and benefit with the expectation
6 * that others will use, modify and enhance the Software and contribute
7 * those enhancements back to the community. However, since we would
8 * like to make the Software available for broadest use, with as few
9 * restrictions as possible permission is hereby granted, free of
10 * charge, to any person obtaining a copy of this Software to deal in
11 * the Software under the copyrights without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sublicense, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 * The name and trademarks of copyright holder(s) may NOT be used in
30 * advertising or publicity pertaining to the Software or any
31 * derivatives without specific, written prior permission.
34 /* Functions for executing OpenFlow actions. */
36 #include <arpa/inet.h>
40 #include "nicira-ext.h"
45 validate_output(struct datapath *dp, const struct sw_flow_key *key,
46 const struct ofp_action_header *ah)
48 struct ofp_action_output *oa = (struct ofp_action_output *)ah;
50 /* To prevent loops, make sure there's no action to send to the
51 * OFP_TABLE virtual port.
53 if (oa->port == htons(OFPP_NONE) || oa->port == key->flow.in_port) {
54 return OFPBAC_BAD_OUT_PORT;
56 return ACT_VALIDATION_OK;
60 do_output(struct datapath *dp, struct ofpbuf *buffer, int in_port,
61 size_t max_len, int out_port, bool ignore_no_fwd)
63 if (out_port != OFPP_CONTROLLER) {
64 dp_output_port(dp, buffer, in_port, out_port, ignore_no_fwd);
66 dp_output_control(dp, buffer, in_port, max_len, OFPR_ACTION);
70 /* Modify vlan tag control information (TCI). Only sets the TCI bits
71 * indicated by 'mask'. If no vlan tag is present, one is added.
74 modify_vlan_tci(struct ofpbuf *buffer, struct sw_flow_key *key,
75 uint16_t tci, uint16_t mask)
77 struct vlan_eth_header *veh;
79 if (key->flow.dl_vlan != htons(OFP_VLAN_NONE)) {
80 /* Modify vlan id, but maintain other TCI values */
82 veh->veth_tci &= ~htons(mask);
83 veh->veth_tci |= htons(tci);
85 /* Insert new vlan id. */
86 struct eth_header *eh = buffer->l2;
87 struct vlan_eth_header tmp;
88 memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN);
89 memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN);
90 tmp.veth_type = htons(ETH_TYPE_VLAN);
91 tmp.veth_tci = htons(tci);
92 tmp.veth_next_type = eh->eth_type;
94 veh = ofpbuf_push_uninit(buffer, VLAN_HEADER_LEN);
95 memcpy(veh, &tmp, sizeof tmp);
96 buffer->l2 = (char*)buffer->l2 - VLAN_HEADER_LEN;
99 key->flow.dl_vlan = veh->veth_tci & htons(VLAN_VID_MASK);
103 /* Remove an existing vlan header if it exists. */
105 vlan_pull_tag(struct ofpbuf *buffer)
107 struct vlan_eth_header *veh = buffer->l2;
109 if (veh->veth_type == htons(ETH_TYPE_VLAN)) {
110 struct eth_header tmp;
112 memcpy(tmp.eth_dst, veh->veth_dst, ETH_ADDR_LEN);
113 memcpy(tmp.eth_src, veh->veth_src, ETH_ADDR_LEN);
114 tmp.eth_type = veh->veth_next_type;
116 buffer->size -= VLAN_HEADER_LEN;
117 buffer->data = (char*)buffer->data + VLAN_HEADER_LEN;
118 buffer->l2 = (char*)buffer->l2 + VLAN_HEADER_LEN;
119 memcpy(buffer->data, &tmp, sizeof tmp);
124 set_vlan_vid(struct ofpbuf *buffer, struct sw_flow_key *key,
125 const struct ofp_action_header *ah)
127 struct ofp_action_vlan_vid *va = (struct ofp_action_vlan_vid *)ah;
128 uint16_t tci = ntohs(va->vlan_vid);
130 modify_vlan_tci(buffer, key, tci, VLAN_VID_MASK);
134 set_vlan_pcp(struct ofpbuf *buffer, struct sw_flow_key *key,
135 const struct ofp_action_header *ah)
137 struct ofp_action_vlan_pcp *va = (struct ofp_action_vlan_pcp *)ah;
138 uint16_t tci = (uint16_t)va->vlan_pcp << 13;
140 modify_vlan_tci(buffer, key, tci, VLAN_PCP_MASK);
144 strip_vlan(struct ofpbuf *buffer, struct sw_flow_key *key,
145 const struct ofp_action_header *ah)
147 vlan_pull_tag(buffer);
148 key->flow.dl_vlan = htons(OFP_VLAN_NONE);
152 set_dl_addr(struct ofpbuf *buffer, struct sw_flow_key *key,
153 const struct ofp_action_header *ah)
155 struct ofp_action_dl_addr *da = (struct ofp_action_dl_addr *)ah;
156 struct eth_header *eh = buffer->l2;
158 if (da->type == htons(OFPAT_SET_DL_SRC)) {
159 memcpy(eh->eth_src, da->dl_addr, sizeof eh->eth_src);
161 memcpy(eh->eth_dst, da->dl_addr, sizeof eh->eth_dst);
166 set_nw_addr(struct ofpbuf *buffer, struct sw_flow_key *key,
167 const struct ofp_action_header *ah)
169 struct ofp_action_nw_addr *na = (struct ofp_action_nw_addr *)ah;
170 uint16_t eth_proto = ntohs(key->flow.dl_type);
172 if (eth_proto == ETH_TYPE_IP) {
173 struct ip_header *nh = buffer->l3;
174 uint8_t nw_proto = key->flow.nw_proto;
175 uint32_t new, *field;
178 field = na->type == OFPAT_SET_NW_SRC ? &nh->ip_src : &nh->ip_dst;
179 if (nw_proto == IP_TYPE_TCP) {
180 struct tcp_header *th = buffer->l4;
181 th->tcp_csum = recalc_csum32(th->tcp_csum, *field, new);
182 } else if (nw_proto == IP_TYPE_UDP) {
183 struct udp_header *th = buffer->l4;
185 th->udp_csum = recalc_csum32(th->udp_csum, *field, new);
187 th->udp_csum = 0xffff;
191 nh->ip_csum = recalc_csum32(nh->ip_csum, *field, new);
197 set_tp_port(struct ofpbuf *buffer, struct sw_flow_key *key,
198 const struct ofp_action_header *ah)
200 struct ofp_action_tp_port *ta = (struct ofp_action_tp_port *)ah;
201 uint16_t eth_proto = ntohs(key->flow.dl_type);
203 if (eth_proto == ETH_TYPE_IP) {
204 uint8_t nw_proto = key->flow.nw_proto;
205 uint16_t new, *field;
208 if (nw_proto == IP_TYPE_TCP) {
209 struct tcp_header *th = buffer->l4;
210 field = ta->type == OFPAT_SET_TP_SRC ? &th->tcp_src : &th->tcp_dst;
211 th->tcp_csum = recalc_csum16(th->tcp_csum, *field, new);
213 } else if (nw_proto == IP_TYPE_UDP) {
214 struct udp_header *th = buffer->l4;
215 field = ta->type == OFPAT_SET_TP_SRC ? &th->udp_src : &th->udp_dst;
216 th->udp_csum = recalc_csum16(th->udp_csum, *field, new);
222 struct openflow_action {
225 uint16_t (*validate)(struct datapath *dp,
226 const struct sw_flow_key *key,
227 const struct ofp_action_header *ah);
228 void (*execute)(struct ofpbuf *buffer,
229 struct sw_flow_key *key,
230 const struct ofp_action_header *ah);
233 static const struct openflow_action of_actions[] = {
235 sizeof(struct ofp_action_output),
236 sizeof(struct ofp_action_output),
238 NULL /* This is optimized into execute_actions */
240 [OFPAT_SET_VLAN_VID] = {
241 sizeof(struct ofp_action_vlan_vid),
242 sizeof(struct ofp_action_vlan_vid),
246 [OFPAT_SET_VLAN_PCP] = {
247 sizeof(struct ofp_action_vlan_pcp),
248 sizeof(struct ofp_action_vlan_pcp),
252 [OFPAT_STRIP_VLAN] = {
253 sizeof(struct ofp_action_header),
254 sizeof(struct ofp_action_header),
258 [OFPAT_SET_DL_SRC] = {
259 sizeof(struct ofp_action_dl_addr),
260 sizeof(struct ofp_action_dl_addr),
264 [OFPAT_SET_DL_DST] = {
265 sizeof(struct ofp_action_dl_addr),
266 sizeof(struct ofp_action_dl_addr),
270 [OFPAT_SET_NW_SRC] = {
271 sizeof(struct ofp_action_nw_addr),
272 sizeof(struct ofp_action_nw_addr),
276 [OFPAT_SET_NW_DST] = {
277 sizeof(struct ofp_action_nw_addr),
278 sizeof(struct ofp_action_nw_addr),
282 [OFPAT_SET_TP_SRC] = {
283 sizeof(struct ofp_action_tp_port),
284 sizeof(struct ofp_action_tp_port),
288 [OFPAT_SET_TP_DST] = {
289 sizeof(struct ofp_action_tp_port),
290 sizeof(struct ofp_action_tp_port),
294 /* OFPAT_VENDOR is not here, since it would blow up the array size. */
297 /* Validate built-in OpenFlow actions. Either returns ACT_VALIDATION_OK
298 * or an OFPET_BAD_ACTION error code. */
300 validate_ofpat(struct datapath *dp, const struct sw_flow_key *key,
301 const struct ofp_action_header *ah, uint16_t type, uint16_t len)
303 int ret = ACT_VALIDATION_OK;
304 const struct openflow_action *act = &of_actions[type];
306 if ((len < act->min_size) || (len > act->max_size)) {
307 return OFPBAC_BAD_LEN;
311 ret = act->validate(dp, key, ah);
317 /* Validate vendor-defined actions. Either returns ACT_VALIDATION_OK
318 * or an OFPET_BAD_ACTION error code. */
320 validate_vendor(struct datapath *dp, const struct sw_flow_key *key,
321 const struct ofp_action_header *ah, uint16_t len)
323 struct ofp_action_vendor_header *avh;
324 int ret = ACT_VALIDATION_OK;
326 if (len < sizeof(struct ofp_action_vendor_header)) {
327 return OFPBAC_BAD_LEN;
330 avh = (struct ofp_action_vendor_header *)ah;
332 switch(ntohl(avh->vendor)) {
334 ret = nx_validate_act(dp, key, avh, len);
338 return OFPBAC_BAD_VENDOR;
344 /* Validates a list of actions. If a problem is found, a code for the
345 * OFPET_BAD_ACTION error type is returned. If the action list validates,
346 * ACT_VALIDATION_OK is returned. */
348 validate_actions(struct datapath *dp, const struct sw_flow_key *key,
349 const struct ofp_action_header *actions, size_t actions_len)
351 uint8_t *p = (uint8_t *)actions;
354 while (actions_len >= sizeof(struct ofp_action_header)) {
355 struct ofp_action_header *ah = (struct ofp_action_header *)p;
356 size_t len = ntohs(ah->len);
359 /* Make there's enough remaining data for the specified length
360 * and that the action length is a multiple of 64 bits. */
361 if ((actions_len < len) || (len % 8) != 0) {
362 return OFPBAC_BAD_LEN;
365 type = ntohs(ah->type);
366 if (type < ARRAY_SIZE(of_actions)) {
367 err = validate_ofpat(dp, key, ah, type, len);
368 if (err != ACT_VALIDATION_OK) {
371 } else if (type == OFPAT_VENDOR) {
372 err = validate_vendor(dp, key, ah, len);
373 if (err != ACT_VALIDATION_OK) {
377 return OFPBAC_BAD_TYPE;
384 /* Check if there's any trailing garbage. */
385 if (actions_len != 0) {
386 return OFPBAC_BAD_LEN;
389 return ACT_VALIDATION_OK;
392 /* Execute a built-in OpenFlow action against 'buffer'. */
394 execute_ofpat(struct ofpbuf *buffer, struct sw_flow_key *key,
395 const struct ofp_action_header *ah, uint16_t type)
397 const struct openflow_action *act = &of_actions[type];
400 act->execute(buffer, key, ah);
404 /* Execute a vendor-defined action against 'buffer'. */
406 execute_vendor(struct ofpbuf *buffer, const struct sw_flow_key *key,
407 const struct ofp_action_header *ah)
409 struct ofp_action_vendor_header *avh
410 = (struct ofp_action_vendor_header *)ah;
412 switch(ntohl(avh->vendor)) {
414 nx_execute_act(buffer, key, avh);
418 /* This should not be possible due to prior validation. */
419 printf("attempt to execute action with unknown vendor: %#x\n",
425 /* Execute a list of actions against 'buffer'. */
426 void execute_actions(struct datapath *dp, struct ofpbuf *buffer,
427 struct sw_flow_key *key,
428 const struct ofp_action_header *actions, size_t actions_len,
431 /* Every output action needs a separate clone of 'buffer', but the common
432 * case is just a single output action, so that doing a clone and then
433 * freeing the original buffer is wasteful. So the following code is
434 * slightly obscure just to avoid that. */
436 size_t max_len=0; /* Initialze to make compiler happy */
437 uint16_t in_port = ntohs(key->flow.in_port);
438 uint8_t *p = (uint8_t *)actions;
442 /* The action list was already validated, so we can be a bit looser
443 * in our sanity-checking. */
444 while (actions_len > 0) {
445 struct ofp_action_header *ah = (struct ofp_action_header *)p;
446 size_t len = htons(ah->len);
448 if (prev_port != -1) {
449 do_output(dp, ofpbuf_clone(buffer), in_port, max_len,
450 prev_port, ignore_no_fwd);
454 if (ah->type == htons(OFPAT_OUTPUT)) {
455 struct ofp_action_output *oa = (struct ofp_action_output *)p;
456 prev_port = ntohs(oa->port);
457 max_len = ntohs(oa->max_len);
459 uint16_t type = ntohs(ah->type);
461 if (type < ARRAY_SIZE(of_actions)) {
462 execute_ofpat(buffer, key, ah, type);
463 } else if (type == OFPAT_VENDOR) {
464 execute_vendor(buffer, key, ah);
471 if (prev_port != -1) {
472 do_output(dp, buffer, in_port, max_len, prev_port, ignore_no_fwd);
474 ofpbuf_delete(buffer);