X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Flearning-switch.c;h=9e028608c72d6270ba1e98f1fd60f9a9938692f1;hb=f80022d9df98d29ee41176a4bc6cb91025da84b8;hp=dc19aa550d3ab53fc20aa36f30add36c9ddb646f;hpb=81a76618be9ea195a1e4a881ba9591728891d10b;p=sliver-openvswitch.git diff --git a/lib/learning-switch.c b/lib/learning-switch.c index dc19aa550..9e028608c 100644 --- a/lib/learning-switch.c +++ b/lib/learning-switch.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,7 +48,7 @@ VLOG_DEFINE_THIS_MODULE(learning_switch); struct lswitch_port { struct hmap_node hmap_node; /* Hash node for port number. */ - uint16_t port_no; /* OpenFlow port number, in host byte order. */ + ofp_port_t port_no; /* OpenFlow port number. */ uint32_t queue_id; /* OpenFlow queue number. */ }; @@ -200,15 +200,19 @@ lswitch_handshake(struct lswitch *sw) error = rconn_send(sw->rconn, msg, NULL); } } + if (protocol & usable_protocols) { + for (i = 0; !error && i < sw->n_default_flows; i++) { + msg = ofputil_encode_flow_mod(&sw->default_flows[i], protocol); + error = rconn_send(sw->rconn, msg, NULL); + } - for (i = 0; !error && i < sw->n_default_flows; i++) { - msg = ofputil_encode_flow_mod(&sw->default_flows[i], protocol); - error = rconn_send(sw->rconn, msg, NULL); - } - - if (error) { - VLOG_INFO_RL(&rl, "%s: failed to queue default flows (%s)", - rconn_get_name(sw->rconn), strerror(error)); + if (error) { + VLOG_INFO_RL(&rl, "%s: failed to queue default flows (%s)", + rconn_get_name(sw->rconn), ovs_strerror(error)); + } + } else { + VLOG_INFO_RL(&rl, "%s: failed to set usable protocol", + rconn_get_name(sw->rconn)); } } sw->protocol = protocol; @@ -233,7 +237,7 @@ lswitch_destroy(struct lswitch *sw) free(node); } shash_destroy(&sw->queue_names); - mac_learning_destroy(sw->ml); + mac_learning_unref(sw->ml); rconn_packet_counter_destroy(sw->queued); free(sw); } @@ -342,6 +346,8 @@ lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg) case OFPTYPE_PORT_MOD: case OFPTYPE_BARRIER_REQUEST: case OFPTYPE_BARRIER_REPLY: + case OFPTYPE_QUEUE_GET_CONFIG_REQUEST: + case OFPTYPE_QUEUE_GET_CONFIG_REPLY: case OFPTYPE_DESC_STATS_REQUEST: case OFPTYPE_DESC_STATS_REPLY: case OFPTYPE_FLOW_STATS_REQUEST: @@ -362,13 +368,30 @@ lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg) case OFPTYPE_FLOW_MOD_TABLE_ID: case OFPTYPE_SET_PACKET_IN_FORMAT: case OFPTYPE_FLOW_AGE: - case OFPTYPE_SET_ASYNC_CONFIG: case OFPTYPE_SET_CONTROLLER_ID: case OFPTYPE_FLOW_MONITOR_STATS_REQUEST: case OFPTYPE_FLOW_MONITOR_STATS_REPLY: case OFPTYPE_FLOW_MONITOR_CANCEL: case OFPTYPE_FLOW_MONITOR_PAUSED: case OFPTYPE_FLOW_MONITOR_RESUMED: + case OFPTYPE_GET_ASYNC_REQUEST: + case OFPTYPE_GET_ASYNC_REPLY: + case OFPTYPE_SET_ASYNC_CONFIG: + case OFPTYPE_METER_MOD: + case OFPTYPE_GROUP_REQUEST: + case OFPTYPE_GROUP_REPLY: + case OFPTYPE_GROUP_DESC_REQUEST: + case OFPTYPE_GROUP_DESC_REPLY: + case OFPTYPE_GROUP_FEATURES_REQUEST: + case OFPTYPE_GROUP_FEATURES_REPLY: + case OFPTYPE_METER_REQUEST: + case OFPTYPE_METER_REPLY: + case OFPTYPE_METER_CONFIG_REQUEST: + case OFPTYPE_METER_CONFIG_REPLY: + case OFPTYPE_METER_FEATURES_REQUEST: + case OFPTYPE_METER_FEATURES_REPLY: + case OFPTYPE_TABLE_FEATURES_REQUEST: + case OFPTYPE_TABLE_FEATURES_REPLY: default: if (VLOG_IS_DBG_ENABLED()) { char *s = ofp_to_string(msg->data, msg->size, 2); @@ -386,7 +409,7 @@ send_features_request(struct lswitch *sw) struct ofp_switch_config *osc; int ofp_version = rconn_get_version(sw->rconn); - assert(ofp_version > 0 && ofp_version < 0xff); + ovs_assert(ofp_version > 0 && ofp_version < 0xff); /* Send OFPT_FEATURES_REQUEST. */ b = ofpraw_alloc(OFPRAW_OFPT_FEATURES_REQUEST, ofp_version, 0); @@ -410,7 +433,7 @@ queue_tx(struct lswitch *sw, struct ofpbuf *b) } else { VLOG_WARN_RL(&rl, "%016llx: %s: send: %s", sw->datapath_id, rconn_get_name(sw->rconn), - strerror(retval)); + ovs_strerror(retval)); } } } @@ -437,26 +460,27 @@ process_switch_features(struct lswitch *sw, struct ofp_header *oh) if (lp && hmap_node_is_null(&lp->hmap_node)) { lp->port_no = port.port_no; hmap_insert(&sw->queue_numbers, &lp->hmap_node, - hash_int(lp->port_no, 0)); + hash_ofp_port(lp->port_no)); } } return 0; } -static uint16_t +static ofp_port_t lswitch_choose_destination(struct lswitch *sw, const struct flow *flow) { - uint16_t out_port; + ofp_port_t out_port; /* Learn the source MAC. */ if (mac_learning_may_learn(sw->ml, flow->dl_src, 0)) { struct mac_entry *mac = mac_learning_insert(sw->ml, flow->dl_src, 0); - if (mac_entry_is_new(mac) || mac->port.i != flow->in_port) { + if (mac_entry_is_new(mac) + || mac->port.ofp_port != flow->in_port.ofp_port) { VLOG_DBG_RL(&rl, "%016llx: learned that "ETH_ADDR_FMT" is on " "port %"PRIu16, sw->datapath_id, - ETH_ADDR_ARGS(flow->dl_src), flow->in_port); + ETH_ADDR_ARGS(flow->dl_src), flow->in_port.ofp_port); - mac->port.i = flow->in_port; + mac->port.ofp_port = flow->in_port.ofp_port; mac_learning_changed(sw->ml, mac); } } @@ -472,8 +496,8 @@ lswitch_choose_destination(struct lswitch *sw, const struct flow *flow) mac = mac_learning_lookup(sw->ml, flow->dl_dst, 0, NULL); if (mac) { - out_port = mac->port.i; - if (out_port == flow->in_port) { + out_port = mac->port.ofp_port; + if (out_port == flow->in_port.ofp_port) { /* Don't send a packet back out its input port. */ return OFPP_NONE; } @@ -489,11 +513,11 @@ lswitch_choose_destination(struct lswitch *sw, const struct flow *flow) } static uint32_t -get_queue_id(const struct lswitch *sw, uint16_t in_port) +get_queue_id(const struct lswitch *sw, ofp_port_t in_port) { const struct lswitch_port *port; - HMAP_FOR_EACH_WITH_HASH (port, hmap_node, hash_int(in_port, 0), + HMAP_FOR_EACH_WITH_HASH (port, hmap_node, hash_ofp_port(in_port), &sw->queue_numbers) { if (port->port_no == in_port) { return port->queue_id; @@ -508,7 +532,7 @@ process_packet_in(struct lswitch *sw, const struct ofp_header *oh) { struct ofputil_packet_in pi; uint32_t queue_id; - uint16_t out_port; + ofp_port_t out_port; uint64_t ofpacts_stub[64 / 8]; struct ofpbuf ofpacts; @@ -518,6 +542,7 @@ process_packet_in(struct lswitch *sw, const struct ofp_header *oh) struct ofpbuf pkt; struct flow flow; + union flow_in_port in_port_; error = ofputil_decode_packet_in(&pi, oh); if (error) { @@ -535,7 +560,9 @@ process_packet_in(struct lswitch *sw, const struct ofp_header *oh) /* Extract flow data from 'opi' into 'flow'. */ ofpbuf_use_const(&pkt, pi.packet, pi.packet_len); - flow_extract(&pkt, 0, pi.fmd.tun_id, pi.fmd.in_port, &flow); + in_port_.ofp_port = pi.fmd.in_port; + flow_extract(&pkt, 0, 0, NULL, &in_port_, &flow); + flow.tunnel.tun_id = pi.fmd.tun_id; /* Choose output port. */ out_port = lswitch_choose_destination(sw, &flow); @@ -545,7 +572,8 @@ process_packet_in(struct lswitch *sw, const struct ofp_header *oh) ofpbuf_use_stack(&ofpacts, ofpacts_stub, sizeof ofpacts_stub); if (out_port == OFPP_NONE) { /* No actions. */ - } else if (queue_id == UINT32_MAX || out_port >= OFPP_MAX) { + } else if (queue_id == UINT32_MAX + || ofp_to_u16(out_port) >= ofp_to_u16(OFPP_MAX)) { ofpact_put_OUTPUT(&ofpacts)->port = out_port; } else { struct ofpact_enqueue *enqueue = ofpact_put_ENQUEUE(&ofpacts);