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.
35 #include <arpa/inet.h>
45 #include "poll-loop.h"
50 #define THIS_MODULE VLM_datapath
53 #define BRIDGE_PORT_NO_FLOOD 0x00000001
55 /* Capabilities supported by this implementation. */
56 #define OFP_SUPPORTED_CAPABILITIES (OFPC_MULTI_PHY_TX)
58 /* Actions supported by this implementation. */
59 #define OFP_SUPPORTED_ACTIONS ( (1 << OFPAT_OUTPUT) \
60 | (1 << OFPAT_SET_DL_VLAN) \
61 | (1 << OFPAT_SET_DL_SRC) \
62 | (1 << OFPAT_SET_DL_DST) \
63 | (1 << OFPAT_SET_NW_SRC) \
64 | (1 << OFPAT_SET_NW_DST) \
65 | (1 << OFPAT_SET_TP_SRC) \
66 | (1 << OFPAT_SET_TP_DST) )
71 struct netdev *netdev;
72 struct list node; /* Element in datapath.ports. */
80 /* Unique identifier for this datapath */
83 struct sw_chain *chain; /* Forwarding rules. */
85 struct ofp_switch_config config;
88 struct sw_port ports[OFPP_MAX];
89 struct list port_list; /* List of ports, for flooding. */
92 void dp_output_port(struct datapath *, struct buffer *,
93 int in_port, int out_port);
94 void dp_update_port_flags(struct datapath *dp, const struct ofp_phy_port *opp);
95 void dp_output_control(struct datapath *, struct buffer *, int in_port,
96 size_t max_len, int reason);
97 static void send_flow_expired(struct datapath *, struct sw_flow *);
98 static void send_port_status(struct sw_port *p, uint8_t status);
99 static void del_switch_port(struct sw_port *p);
100 static void execute_actions(struct datapath *, struct buffer *,
101 int in_port, const struct sw_flow_key *,
102 const struct ofp_action *, int n_actions);
103 static void modify_vlan(struct buffer *buffer, const struct sw_flow_key *key,
104 const struct ofp_action *a);
105 static void modify_nh(struct buffer *buffer, uint16_t eth_proto,
106 uint8_t nw_proto, const struct ofp_action *a);
107 static void modify_th(struct buffer *buffer, uint16_t eth_proto,
108 uint8_t nw_proto, const struct ofp_action *a);
110 /* Buffers are identified to userspace by a 31-bit opaque ID. We divide the ID
111 * into a buffer number (low bits) and a cookie (high bits). The buffer number
112 * is an index into an array of buffers. The cookie distinguishes between
113 * different packets that have occupied a single buffer. Thus, the more
114 * buffers we have, the lower-quality the cookie... */
115 #define PKT_BUFFER_BITS 8
116 #define N_PKT_BUFFERS (1 << PKT_BUFFER_BITS)
117 #define PKT_BUFFER_MASK (N_PKT_BUFFERS - 1)
119 #define PKT_COOKIE_BITS (32 - PKT_BUFFER_BITS)
121 void fwd_port_input(struct datapath *, struct buffer *, int in_port);
122 int fwd_control_input(struct datapath *, const void *, size_t);
124 uint32_t save_buffer(struct buffer *);
125 static struct buffer *retrieve_buffer(uint32_t id);
126 static void discard_buffer(uint32_t id);
128 static int port_no(struct datapath *dp, struct sw_port *p)
130 assert(p >= dp->ports && p < &dp->ports[ARRAY_SIZE(dp->ports)]);
131 return p - dp->ports;
134 /* Generates a unique datapath id. It incorporates the datapath index
135 * and a hardware address, if available. If not, it generates a random
139 gen_datapath_id(void)
141 /* Choose a random datapath id. */
147 for (i = 0; i < ETH_ADDR_LEN; i++) {
148 id |= (uint64_t)(rand() & 0xff) << (8*(ETH_ADDR_LEN-1 - i));
155 dp_new(struct datapath **dp_, uint64_t dpid, struct rconn *rconn)
159 dp = calloc(1, sizeof *dp);
164 dp->last_timeout = time(0);
166 dp->id = dpid <= UINT64_C(0xffffffffffff) ? dpid : gen_datapath_id();
167 dp->chain = chain_create();
169 VLOG_ERR("could not create chain");
174 list_init(&dp->port_list);
175 dp->config.flags = 0;
176 dp->config.miss_send_len = OFP_DEFAULT_MISS_SEND_LEN;
182 dp_add_port(struct datapath *dp, const char *name)
184 struct netdev *netdev;
188 error = netdev_open(name, &netdev);
193 for (p = dp->ports; ; p++) {
194 if (p >= &dp->ports[ARRAY_SIZE(dp->ports)]) {
196 } else if (!p->netdev) {
203 list_push_back(&dp->port_list, &p->node);
205 /* Notify the ctlpath that this port has been added */
206 send_port_status(p, OFPPR_ADD);
212 dp_run(struct datapath *dp)
214 time_t now = time(0);
215 struct sw_port *p, *n;
216 struct buffer *buffer = NULL;
219 if (now != dp->last_timeout) {
220 struct list deleted = LIST_INITIALIZER(&deleted);
221 struct sw_flow *f, *n;
223 chain_timeout(dp->chain, &deleted);
224 LIST_FOR_EACH_SAFE (f, n, struct sw_flow, node, &deleted) {
225 send_flow_expired(dp, f);
226 list_remove(&f->node);
229 dp->last_timeout = now;
231 poll_timer_wait(1000);
233 LIST_FOR_EACH_SAFE (p, n, struct sw_port, node, &dp->port_list) {
237 /* Allocate buffer with some headroom to add headers in forwarding
238 * to the controller or adding a vlan tag, plus an extra 2 bytes to
239 * allow IP headers to be aligned on a 4-byte boundary. */
240 const int headroom = 128 + 2;
241 const int hard_header = VLAN_ETH_HEADER_LEN;
242 const int mtu = netdev_get_mtu(p->netdev);
243 buffer = buffer_new(headroom + hard_header + mtu);
244 buffer->data += headroom;
246 error = netdev_recv(p->netdev, buffer);
248 fwd_port_input(dp, buffer, port_no(dp, p));
250 } else if (error != EAGAIN) {
251 VLOG_ERR("Error receiving data from %s: %s",
252 netdev_get_name(p->netdev), strerror(error));
256 buffer_delete(buffer);
258 /* Process a number of commands from the controller, but cap it at a
259 * reasonable number so that other processing doesn't starve. */
260 for (i = 0; i < 50; i++) {
261 struct buffer *buffer = rconn_recv(dp->rconn);
265 fwd_control_input(dp, buffer->data, buffer->size);
266 buffer_delete(buffer);
269 rconn_run(dp->rconn);
273 dp_wait(struct datapath *dp)
277 LIST_FOR_EACH (p, struct sw_port, node, &dp->port_list) {
278 netdev_recv_wait(p->netdev);
280 rconn_recv_wait(dp->rconn);
283 /* Delete 'p' from switch. */
285 del_switch_port(struct sw_port *p)
287 send_port_status(p, OFPPR_DELETE);
288 netdev_close(p->netdev);
290 list_remove(&p->node);
294 dp_destroy(struct datapath *dp)
296 struct sw_port *p, *n;
302 LIST_FOR_EACH_SAFE (p, n, struct sw_port, node, &dp->port_list) {
305 chain_destroy(dp->chain);
310 flood(struct datapath *dp, struct buffer *buffer, int in_port)
316 LIST_FOR_EACH (p, struct sw_port, node, &dp->port_list) {
317 if (port_no(dp, p) == in_port || p->flags & BRIDGE_PORT_NO_FLOOD) {
320 if (prev_port != -1) {
321 dp_output_port(dp, buffer_clone(buffer), in_port, prev_port);
323 prev_port = port_no(dp, p);
326 dp_output_port(dp, buffer, in_port, prev_port);
328 buffer_delete(buffer);
334 output_packet(struct datapath *dp, struct buffer *buffer, int out_port)
336 if (out_port >= 0 && out_port < OFPP_MAX) {
337 struct sw_port *p = &dp->ports[out_port];
338 if (p->netdev != NULL) {
339 netdev_send(p->netdev, buffer);
344 buffer_delete(buffer);
345 /* FIXME: ratelimit */
346 VLOG_DBG("can't forward to bad port %d\n", out_port);
349 /* Takes ownership of 'buffer' and transmits it to 'out_port' on 'dp'.
352 dp_output_port(struct datapath *dp, struct buffer *buffer,
353 int in_port, int out_port)
357 if (out_port == OFPP_FLOOD) {
358 flood(dp, buffer, in_port);
359 } else if (out_port == OFPP_CONTROLLER) {
360 dp_output_control(dp, buffer, in_port, 0, OFPR_ACTION);
362 output_packet(dp, buffer, out_port);
366 /* Takes ownership of 'buffer' and transmits it to 'dp''s controller. If the
367 * packet can be saved in a buffer, then only the first max_len bytes of
368 * 'buffer' are sent; otherwise, all of 'buffer' is sent. 'reason' indicates
369 * why 'buffer' is being sent. 'max_len' sets the maximum number of bytes that
370 * the caller wants to be sent; a value of 0 indicates the entire packet should
373 dp_output_control(struct datapath *dp, struct buffer *buffer, int in_port,
374 size_t max_len, int reason)
376 struct ofp_packet_in *opi;
380 buffer_id = save_buffer(buffer);
381 total_len = buffer->size;
382 if (buffer_id != UINT32_MAX && buffer->size > max_len) {
383 buffer->size = max_len;
386 opi = buffer_push_uninit(buffer, offsetof(struct ofp_packet_in, data));
387 opi->header.version = OFP_VERSION;
388 opi->header.type = OFPT_PACKET_IN;
389 opi->header.length = htons(buffer->size);
390 opi->header.xid = htonl(0);
391 opi->buffer_id = htonl(buffer_id);
392 opi->total_len = htons(total_len);
393 opi->in_port = htons(in_port);
394 opi->reason = reason;
396 rconn_send(dp->rconn, buffer);
399 static void fill_port_desc(struct datapath *dp, struct sw_port *p,
400 struct ofp_phy_port *desc)
402 desc->port_no = htons(port_no(dp, p));
403 strncpy((char *) desc->name, netdev_get_name(p->netdev),
405 desc->name[sizeof desc->name - 1] = '\0';
406 memcpy(desc->hw_addr, netdev_get_etheraddr(p->netdev), ETH_ADDR_LEN);
407 desc->flags = htonl(p->flags);
408 desc->features = htonl(netdev_get_features(p->netdev));
409 desc->speed = htonl(netdev_get_speed(p->netdev));
413 dp_send_features_reply(struct datapath *dp, uint32_t xid)
415 struct buffer *buffer;
416 struct ofp_switch_features *ofr;
419 buffer = buffer_new(sizeof *ofr);
420 ofr = buffer_put_uninit(buffer, sizeof *ofr);
421 memset(ofr, 0, sizeof *ofr);
422 ofr->header.version = OFP_VERSION;
423 ofr->header.type = OFPT_FEATURES_REPLY;
424 ofr->header.xid = xid;
425 ofr->datapath_id = htonll(dp->id);
426 ofr->n_exact = htonl(2 * TABLE_HASH_MAX_FLOWS);
427 ofr->n_mac_only = htonl(TABLE_MAC_MAX_FLOWS);
428 ofr->n_compression = 0; /* Not supported */
429 ofr->n_general = htonl(TABLE_LINEAR_MAX_FLOWS);
430 ofr->buffer_mb = htonl(UINT32_MAX);
431 ofr->n_buffers = htonl(N_PKT_BUFFERS);
432 ofr->capabilities = htonl(OFP_SUPPORTED_CAPABILITIES);
433 ofr->actions = htonl(OFP_SUPPORTED_ACTIONS);
434 LIST_FOR_EACH (p, struct sw_port, node, &dp->port_list) {
435 struct ofp_phy_port *opp = buffer_put_uninit(buffer, sizeof *opp);
436 memset(opp, 0, sizeof *opp);
437 fill_port_desc(dp, p, opp);
439 ofr = buffer_at_assert(buffer, 0, sizeof *ofr);
440 ofr->header.length = htons(buffer->size);
441 rconn_send(dp->rconn, buffer);
445 dp_update_port_flags(struct datapath *dp, const struct ofp_phy_port *opp)
449 p = &dp->ports[htons(opp->port_no)];
451 /* Make sure the port id hasn't changed since this was sent */
452 if (!p || memcmp(opp->hw_addr, netdev_get_etheraddr(p->netdev),
456 p->flags = htonl(opp->flags);
460 send_port_status(struct sw_port *p, uint8_t status)
462 struct buffer *buffer;
463 struct ofp_port_status *ops;
464 buffer = buffer_new(sizeof *ops);
465 ops = buffer_put_uninit(buffer, sizeof *ops);
466 ops->header.version = OFP_VERSION;
467 ops->header.type = OFPT_PORT_STATUS;
468 ops->header.length = htons(sizeof(*ops));
469 ops->header.xid = htonl(0);
470 ops->reason = status;
471 fill_port_desc(p->dp, p, &ops->desc);
472 rconn_send(p->dp->rconn, buffer);
476 send_flow_expired(struct datapath *dp, struct sw_flow *flow)
478 struct buffer *buffer;
479 struct ofp_flow_expired *ofe;
480 buffer = buffer_new(sizeof *ofe);
481 ofe = buffer_put_uninit(buffer, sizeof *ofe);
482 ofe->header.version = OFP_VERSION;
483 ofe->header.type = OFPT_FLOW_EXPIRED;
484 ofe->header.length = htons(sizeof(*ofe));
485 ofe->header.xid = htonl(0);
486 flow_fill_match(&ofe->match, &flow->key);
487 ofe->duration = htonl(flow->timeout - flow->max_idle - flow->created);
488 ofe->packet_count = htonll(flow->packet_count);
489 ofe->byte_count = htonll(flow->byte_count);
490 rconn_send(dp->rconn, buffer);
493 /* 'buffer' was received on 'in_port', a physical switch port between 0 and
494 * OFPP_MAX. Process it according to 'chain'. */
495 void fwd_port_input(struct datapath *dp, struct buffer *buffer, int in_port)
497 struct sw_flow_key key;
498 struct sw_flow *flow;
501 flow_extract(buffer, in_port, &key.flow);
502 flow = chain_lookup(dp->chain, &key);
504 flow_used(flow, buffer);
505 execute_actions(dp, buffer, in_port, &key,
506 flow->actions, flow->n_actions);
508 dp_output_control(dp, buffer, in_port, dp->config.miss_send_len,
514 do_output(struct datapath *dp, struct buffer *buffer, int in_port,
515 size_t max_len, int out_port)
517 if (out_port != OFPP_CONTROLLER) {
518 dp_output_port(dp, buffer, in_port, out_port);
520 dp_output_control(dp, buffer, in_port, max_len, OFPR_ACTION);
525 execute_actions(struct datapath *dp, struct buffer *buffer,
526 int in_port, const struct sw_flow_key *key,
527 const struct ofp_action *actions, int n_actions)
529 /* Every output action needs a separate clone of 'buffer', but the common
530 * case is just a single output action, so that doing a clone and then
531 * freeing the original buffer is wasteful. So the following code is
532 * slightly obscure just to avoid that. */
534 size_t max_len=0; /* Initialze to make compiler happy */
539 eth_proto = ntohs(key->flow.dl_type);
541 for (i = 0; i < n_actions; i++) {
542 const struct ofp_action *a = &actions[i];
543 struct eth_header *eh = buffer->l2;
545 if (prev_port != -1) {
546 do_output(dp, buffer_clone(buffer), in_port, max_len, prev_port);
550 switch (ntohs(a->type)) {
552 prev_port = ntohs(a->arg.output.port);
553 max_len = ntohs(a->arg.output.max_len);
556 case OFPAT_SET_DL_VLAN:
557 modify_vlan(buffer, key, a);
560 case OFPAT_SET_DL_SRC:
561 memcpy(eh->eth_src, a->arg.dl_addr, sizeof eh->eth_src);
564 case OFPAT_SET_DL_DST:
565 memcpy(eh->eth_dst, a->arg.dl_addr, sizeof eh->eth_dst);
568 case OFPAT_SET_NW_SRC:
569 case OFPAT_SET_NW_DST:
570 modify_nh(buffer, eth_proto, key->flow.nw_proto, a);
573 case OFPAT_SET_TP_SRC:
574 case OFPAT_SET_TP_DST:
575 modify_th(buffer, eth_proto, key->flow.nw_proto, a);
583 do_output(dp, buffer, in_port, max_len, prev_port);
585 buffer_delete(buffer);
588 /* Returns the new checksum for a packet in which the checksum field previously
589 * contained 'old_csum' and in which a field that contained 'old_u16' was
590 * changed to contain 'new_u16'. */
592 recalc_csum16(uint16_t old_csum, uint16_t old_u16, uint16_t new_u16)
594 /* Ones-complement arithmetic is endian-independent, so this code does not
595 * use htons() or ntohs().
597 * See RFC 1624 for formula and explanation. */
598 uint16_t hc_complement = ~old_csum;
599 uint16_t m_complement = ~old_u16;
600 uint16_t m_prime = new_u16;
601 uint32_t sum = hc_complement + m_complement + m_prime;
602 uint16_t hc_prime_complement = sum + (sum >> 16);
603 return ~hc_prime_complement;
606 /* Returns the new checksum for a packet in which the checksum field previously
607 * contained 'old_csum' and in which a field that contained 'old_u32' was
608 * changed to contain 'new_u32'. */
610 recalc_csum32(uint16_t old_csum, uint32_t old_u32, uint32_t new_u32)
612 return recalc_csum16(recalc_csum16(old_csum, old_u32, new_u32),
613 old_u32 >> 16, new_u32 >> 16);
616 static void modify_nh(struct buffer *buffer, uint16_t eth_proto,
617 uint8_t nw_proto, const struct ofp_action *a)
619 if (eth_proto == ETH_TYPE_IP) {
620 struct ip_header *nh = buffer->l3;
621 uint32_t new, *field;
623 new = a->arg.nw_addr;
624 field = a->type == OFPAT_SET_NW_SRC ? &nh->ip_src : &nh->ip_dst;
625 if (nw_proto == IP_TYPE_TCP) {
626 struct tcp_header *th = buffer->l4;
627 th->tcp_csum = recalc_csum32(th->tcp_csum, *field, new);
628 } else if (nw_proto == IP_TYPE_UDP) {
629 struct udp_header *th = buffer->l4;
631 th->udp_csum = recalc_csum32(th->udp_csum, *field, new);
633 th->udp_csum = 0xffff;
637 nh->ip_csum = recalc_csum32(nh->ip_csum, *field, new);
642 static void modify_th(struct buffer *buffer, uint16_t eth_proto,
643 uint8_t nw_proto, const struct ofp_action *a)
645 if (eth_proto == ETH_TYPE_IP) {
646 uint16_t new, *field;
650 if (nw_proto == IP_TYPE_TCP) {
651 struct tcp_header *th = buffer->l4;
652 field = a->type == OFPAT_SET_TP_SRC ? &th->tcp_src : &th->tcp_dst;
653 th->tcp_csum = recalc_csum16(th->tcp_csum, *field, new);
655 } else if (nw_proto == IP_TYPE_UDP) {
656 struct udp_header *th = buffer->l4;
657 field = a->type == OFPAT_SET_TP_SRC ? &th->udp_src : &th->udp_dst;
658 th->udp_csum = recalc_csum16(th->udp_csum, *field, new);
665 modify_vlan(struct buffer *buffer,
666 const struct sw_flow_key *key, const struct ofp_action *a)
668 uint16_t new_id = a->arg.vlan_id;
669 struct vlan_eth_header *veh;
671 if (new_id != OFP_VLAN_NONE) {
672 if (key->flow.dl_vlan != htons(OFP_VLAN_NONE)) {
673 /* Modify vlan id, but maintain other TCI values */
675 veh->veth_tci &= ~htons(VLAN_VID);
676 veh->veth_tci |= htons(new_id);
678 /* Insert new vlan id. */
679 struct eth_header *eh = buffer->l2;
680 struct vlan_eth_header tmp;
681 memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN);
682 memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN);
683 tmp.veth_type = htons(ETH_TYPE_VLAN);
684 tmp.veth_tci = new_id;
685 tmp.veth_next_type = eh->eth_type;
687 veh = buffer_push_uninit(buffer, VLAN_HEADER_LEN);
688 memcpy(veh, &tmp, sizeof tmp);
689 buffer->l2 -= VLAN_HEADER_LEN;
692 /* Remove an existing vlan header if it exists */
694 if (veh->veth_type == htons(ETH_TYPE_VLAN)) {
695 struct eth_header tmp;
697 memcpy(tmp.eth_dst, veh->veth_dst, ETH_ADDR_LEN);
698 memcpy(tmp.eth_src, veh->veth_src, ETH_ADDR_LEN);
699 tmp.eth_type = veh->veth_next_type;
701 buffer->size -= VLAN_HEADER_LEN;
702 buffer->data += VLAN_HEADER_LEN;
703 buffer->l2 += VLAN_HEADER_LEN;
704 memcpy(buffer->data, &tmp, sizeof tmp);
710 recv_features_request(struct datapath *dp, const void *msg)
712 struct ofp_header *ofr = msg;
713 dp_send_features_reply(dp, ofr->xid);
718 recv_get_config_request(struct datapath *dp, const void *msg)
720 struct ofp_header *gcr = msg;
721 struct buffer *buffer;
722 struct ofp_switch_config *osc;
724 buffer = buffer_new(sizeof dp->config);
725 osc = buffer_put(buffer, &dp->config, sizeof dp->config);
726 osc->header.version = OFP_VERSION;
727 osc->header.type = OFPT_GET_CONFIG_REPLY;
728 osc->header.length = htons(sizeof *osc);
729 osc->header.xid = gcr->xid;
730 rconn_send(dp->rconn, buffer);
735 recv_set_config(struct datapath *dp, const void *msg)
737 const struct ofp_switch_config *osc = msg;
743 recv_packet_out(struct datapath *dp, const void *msg)
745 const struct ofp_packet_out *opo = msg;
747 if (ntohl(opo->buffer_id) == (uint32_t) -1) {
748 /* FIXME: can we avoid copying data here? */
749 int data_len = ntohs(opo->header.length) - sizeof *opo;
750 struct buffer *buffer = buffer_new(data_len);
751 buffer_put(buffer, opo->u.data, data_len);
752 dp_output_port(dp, buffer,
753 ntohs(opo->in_port), ntohs(opo->out_port));
755 struct sw_flow_key key;
756 struct buffer *buffer;
759 buffer = retrieve_buffer(ntohl(opo->buffer_id));
764 n_acts = (ntohs(opo->header.length) - sizeof *opo)
765 / sizeof *opo->u.actions;
766 flow_extract(buffer, ntohs(opo->in_port), &key.flow);
767 execute_actions(dp, buffer, ntohs(opo->in_port),
768 &key, opo->u.actions, n_acts);
774 recv_port_mod(struct datapath *dp, const void *msg)
776 const struct ofp_port_mod *opm = msg;
778 dp_update_port_flags(dp, &opm->desc);
784 add_flow(struct datapath *dp, const struct ofp_flow_mod *ofm)
788 struct sw_flow *flow;
791 /* Check number of actions. */
792 n_acts = (ntohs(ofm->header.length) - sizeof *ofm) / sizeof *ofm->actions;
793 if (n_acts > MAX_ACTIONS) {
798 /* Allocate memory. */
799 flow = flow_alloc(n_acts);
804 flow_extract_match(&flow->key, &ofm->match);
805 flow->group_id = ntohl(ofm->group_id);
806 flow->max_idle = ntohs(ofm->max_idle);
807 flow->timeout = time(0) + flow->max_idle; /* FIXME */
808 flow->n_actions = n_acts;
809 flow->created = time(0); /* FIXME */
810 flow->byte_count = 0;
811 flow->packet_count = 0;
812 memcpy(flow->actions, ofm->actions, n_acts * sizeof *flow->actions);
815 error = chain_insert(dp->chain, flow);
817 goto error_free_flow;
820 if (ntohl(ofm->buffer_id) != UINT32_MAX) {
821 struct buffer *buffer = retrieve_buffer(ntohl(ofm->buffer_id));
823 struct sw_flow_key key;
824 uint16_t in_port = ntohs(ofm->match.in_port);
825 flow_used(flow, buffer);
826 flow_extract(buffer, in_port, &key.flow);
827 execute_actions(dp, buffer, in_port, &key, ofm->actions, n_acts);
837 if (ntohl(ofm->buffer_id) != (uint32_t) -1)
838 discard_buffer(ntohl(ofm->buffer_id));
843 recv_flow(struct datapath *dp, const void *msg)
845 const struct ofp_flow_mod *ofm = msg;
846 uint16_t command = ntohs(ofm->command);
848 if (command == OFPFC_ADD) {
849 return add_flow(dp, ofm);
850 } else if (command == OFPFC_DELETE) {
851 struct sw_flow_key key;
852 flow_extract_match(&key, &ofm->match);
853 return chain_delete(dp->chain, &key, 0) ? 0 : -ESRCH;
854 } else if (command == OFPFC_DELETE_STRICT) {
855 struct sw_flow_key key;
856 flow_extract_match(&key, &ofm->match);
857 return chain_delete(dp->chain, &key, 1) ? 0 : -ESRCH;
863 /* 'msg', which is 'length' bytes long, was received from the control path.
864 * Apply it to 'chain'. */
866 fwd_control_input(struct datapath *dp, const void *msg, size_t length)
869 struct openflow_packet {
871 int (*handler)(struct datapath *, const void *);
874 static const struct openflow_packet packets[] = {
875 [OFPT_FEATURES_REQUEST] = {
876 sizeof (struct ofp_header),
877 recv_features_request,
879 [OFPT_GET_CONFIG_REQUEST] = {
880 sizeof (struct ofp_header),
881 recv_get_config_request,
883 [OFPT_SET_CONFIG] = {
884 sizeof (struct ofp_switch_config),
887 [OFPT_PACKET_OUT] = {
888 sizeof (struct ofp_packet_out),
892 sizeof (struct ofp_flow_mod),
896 sizeof (struct ofp_port_mod),
901 const struct openflow_packet *pkt;
902 struct ofp_header *oh;
904 if (length < sizeof(struct ofp_header))
907 oh = (struct ofp_header *) msg;
908 if (oh->version != 1 || oh->type >= ARRAY_SIZE(packets)
909 || ntohs(oh->length) > length)
912 pkt = &packets[oh->type];
915 if (length < pkt->min_size)
918 return pkt->handler(dp, msg);
921 /* Packet buffering. */
923 #define OVERWRITE_SECS 1
925 struct packet_buffer {
926 struct buffer *buffer;
931 static struct packet_buffer buffers[N_PKT_BUFFERS];
932 static unsigned int buffer_idx;
934 uint32_t save_buffer(struct buffer *buffer)
936 struct packet_buffer *p;
939 buffer_idx = (buffer_idx + 1) & PKT_BUFFER_MASK;
940 p = &buffers[buffer_idx];
942 /* Don't buffer packet if existing entry is less than
943 * OVERWRITE_SECS old. */
944 if (time(0) < p->timeout) { /* FIXME */
947 buffer_delete(p->buffer);
950 /* Don't use maximum cookie value since the all-bits-1 id is
952 if (++p->cookie >= (1u << PKT_COOKIE_BITS) - 1)
954 p->buffer = buffer_clone(buffer); /* FIXME */
955 p->timeout = time(0) + OVERWRITE_SECS; /* FIXME */
956 id = buffer_idx | (p->cookie << PKT_BUFFER_BITS);
961 static struct buffer *retrieve_buffer(uint32_t id)
963 struct buffer *buffer = NULL;
964 struct packet_buffer *p;
966 p = &buffers[id & PKT_BUFFER_MASK];
967 if (p->cookie == id >> PKT_BUFFER_BITS) {
971 printf("cookie mismatch: %x != %x\n",
972 id >> PKT_BUFFER_BITS, p->cookie);
978 static void discard_buffer(uint32_t id)
980 struct packet_buffer *p;
982 p = &buffers[id & PKT_BUFFER_MASK];
983 if (p->cookie == id >> PKT_BUFFER_BITS) {
984 buffer_delete(p->buffer);