struct ofport {
struct hmap_node hmap_node; /* In struct ofproto's "ports" hmap. */
struct netdev *netdev;
- struct ofp_phy_port opp; /* In host byte order. */
+ struct ofp_phy_port opp;
uint16_t odp_port;
struct cfm *cfm; /* Connectivity Fault Management, if any. */
};
static void facet_make_actions(struct ofproto *, struct facet *,
const struct ofpbuf *packet);
+static void facet_reset_dp_stats(struct facet *, struct dpif_flow_stats *);
static void facet_update_stats(struct ofproto *, struct facet *,
const struct dpif_flow_stats *);
static void facet_push_stats(struct ofproto *, struct facet *);
ofproto_port_is_floodable(struct ofproto *ofproto, uint16_t odp_port)
{
struct ofport *ofport = get_port(ofproto, odp_port);
- return ofport && !(ofport->opp.config & OFPPC_NO_FLOOD);
+ return ofport && !(ofport->opp.config & htonl(OFPPC_NO_FLOOD));
}
-/* Sends 'packet' out of port 'port_no' within 'p'. If 'vlan_tci' is zero the
- * packet will not have any 802.1Q hader; if it is nonzero, then the packet
- * will be sent with the VLAN TCI specified by 'vlan_tci & ~VLAN_CFI'.
+/* Sends 'packet' out of port 'port_no' within 'p'.
*
* Returns 0 if successful, otherwise a positive errno value. */
int
ofproto_send_packet(struct ofproto *ofproto,
- uint32_t port_no, uint16_t vlan_tci,
- const struct ofpbuf *packet)
+ uint32_t port_no, const struct ofpbuf *packet)
{
struct ofpbuf odp_actions;
int error;
ofpbuf_init(&odp_actions, 32);
- if (vlan_tci != 0) {
- nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_SET_DL_TCI,
- ntohs(vlan_tci & ~VLAN_CFI));
- }
nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_OUTPUT, port_no);
error = dpif_execute(ofproto->dpif, odp_actions.data, odp_actions.size,
packet);
}
/* Opens and returns a netdev for 'dpif_port', or a null pointer if the netdev
- * cannot be opened. On success, also fills in 'opp', in *HOST* byte order. */
+ * cannot be opened. On success, also fills in 'opp'. */
static struct netdev *
ofport_open(const struct dpif_port *dpif_port, struct ofp_phy_port *opp)
{
+ uint32_t curr, advertised, supported, peer;
struct netdev_options netdev_options;
enum netdev_flags flags;
struct netdev *netdev;
}
netdev_get_flags(netdev, &flags);
+ netdev_get_features(netdev, &curr, &advertised, &supported, &peer);
- opp->port_no = odp_port_to_ofp_port(dpif_port->port_no);
+ opp->port_no = htons(odp_port_to_ofp_port(dpif_port->port_no));
netdev_get_etheraddr(netdev, opp->hw_addr);
ovs_strzcpy(opp->name, dpif_port->name, sizeof opp->name);
- opp->config = flags & NETDEV_UP ? 0 : OFPPC_PORT_DOWN;
- opp->state = netdev_get_carrier(netdev) ? 0 : OFPPS_LINK_DOWN;
- netdev_get_features(netdev, &opp->curr, &opp->advertised,
- &opp->supported, &opp->peer);
+ opp->config = flags & NETDEV_UP ? 0 : htonl(OFPPC_PORT_DOWN);
+ opp->state = netdev_get_carrier(netdev) ? 0 : htonl(OFPPS_LINK_DOWN);
+ opp->curr = htonl(curr);
+ opp->advertised = htonl(advertised);
+ opp->supported = htonl(supported);
+ opp->peer = htonl(peer);
+
return netdev;
}
BUILD_ASSERT_DECL(sizeof *a == 48); /* Detect ofp_phy_port changes. */
return (!memcmp(a->hw_addr, b->hw_addr, sizeof a->hw_addr)
&& a->state == b->state
- && !((a->config ^ b->config) & OFPPC_PORT_DOWN)
+ && !((a->config ^ b->config) & htonl(OFPPC_PORT_DOWN))
&& a->curr == b->curr
&& a->advertised == b->advertised
&& a->supported == b->supported
ofport = xmalloc(sizeof *ofport);
ofport->netdev = netdev;
ofport->opp = *opp;
- ofport->odp_port = ofp_port_to_odp_port(opp->port_no);
+ ofport->odp_port = ofp_port_to_odp_port(ntohs(opp->port_no));
ofport->cfm = NULL;
/* Add port to 'p'. */
struct netdev *netdev, struct ofp_phy_port *opp)
{
memcpy(port->opp.hw_addr, opp->hw_addr, ETH_ADDR_LEN);
- port->opp.config = ((port->opp.config & ~OFPPC_PORT_DOWN)
- | (opp->config & OFPPC_PORT_DOWN));
+ port->opp.config = ((port->opp.config & ~htonl(OFPPC_PORT_DOWN))
+ | (opp->config & htonl(OFPPC_PORT_DOWN)));
port->opp.state = opp->state;
port->opp.curr = opp->curr;
port->opp.advertised = opp->advertised;
ccm = eth_compose(&packet, eth_addr_ccm, ofport->opp.hw_addr,
ETH_TYPE_CFM, sizeof *ccm);
cfm_compose_ccm(ofport->cfm, ccm);
- ofproto_send_packet(ofproto, ofport->odp_port, 0, &packet);
+ ofproto_send_packet(ofproto, ofport->odp_port, &packet);
ofpbuf_uninit(&packet);
}
}
ofpbuf_delete(odp_actions);
}
+/* Updates 'facet''s flow in the datapath setting its actions to 'actions_len'
+ * bytes of actions in 'actions'. If 'stats' is non-null, statistics counters
+ * in the datapath will be zeroed and 'stats' will be updated with traffic new
+ * since 'facet' was last updated.
+ *
+ * Returns 0 if successful, otherwise a positive errno value.*/
static int
facet_put__(struct ofproto *ofproto, struct facet *facet,
const struct nlattr *actions, size_t actions_len,
struct odputil_keybuf keybuf;
enum dpif_flow_put_flags flags;
struct ofpbuf key;
+ int ret;
flags = DPIF_FP_CREATE | DPIF_FP_MODIFY;
if (stats) {
flags |= DPIF_FP_ZERO_STATS;
- facet->dp_packet_count = 0;
- facet->dp_byte_count = 0;
}
ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
odp_flow_key_from_flow(&key, &facet->flow);
- return dpif_flow_put(ofproto->dpif, flags, key.data, key.size,
- actions, actions_len, stats);
+ ret = dpif_flow_put(ofproto->dpif, flags, key.data, key.size,
+ actions, actions_len, stats);
+
+ if (stats) {
+ facet_reset_dp_stats(facet, stats);
+ }
+
+ return ret;
}
/* If 'facet' is installable, inserts or re-inserts it into 'p''s datapath. If
struct odputil_keybuf keybuf;
struct dpif_flow_stats stats;
struct ofpbuf key;
+ int error;
ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
odp_flow_key_from_flow(&key, &facet->flow);
- if (!dpif_flow_del(p->dpif, key.data, key.size, &stats)) {
+ error = dpif_flow_del(p->dpif, key.data, key.size, &stats);
+ facet_reset_dp_stats(facet, &stats);
+ if (!error) {
facet_update_stats(p, facet, &stats);
}
+
facet->installed = false;
- facet->dp_packet_count = 0;
- facet->dp_byte_count = 0;
} else {
assert(facet->dp_packet_count == 0);
assert(facet->dp_byte_count == 0);
htons(OFPP_CONTROLLER)));
}
+/* Resets 'facet''s datapath statistics counters. This should be called when
+ * 'facet''s statistics are cleared in the datapath. If 'stats' is non-null,
+ * it should contain the statistics returned by dpif when 'facet' was reset in
+ * the datapath. 'stats' will be modified to only included statistics new
+ * since 'facet' was last updated. */
+static void
+facet_reset_dp_stats(struct facet *facet, struct dpif_flow_stats *stats)
+{
+ if (stats && facet->dp_packet_count < stats->n_packets
+ && facet->dp_byte_count < stats->n_bytes) {
+ stats->n_packets -= facet->dp_packet_count;
+ stats->n_bytes -= facet->dp_byte_count;
+ }
+
+ facet->dp_packet_count = 0;
+ facet->dp_byte_count = 0;
+}
+
/* Folds all of 'facet''s statistics into its rule. Also updates the
* accounting ofhook and emits a NetFlow expiration if appropriate. All of
* 'facet''s statistics in the datapath should have been zeroed and folded into
(1u << OFPAT_ENQUEUE));
HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
- hton_ofp_phy_port(ofpbuf_put(buf, &port->opp, sizeof port->opp));
+ ofpbuf_put(buf, &port->opp, sizeof port->opp);
}
ofconn_send_reply(ofconn, buf);
const struct ofport *ofport = get_port(ctx->ofproto, port);
if (ofport) {
- if (ofport->opp.config & OFPPC_NO_FWD) {
+ if (ofport->opp.config & htonl(OFPPC_NO_FWD)) {
/* Forwarding disabled on port. */
return;
}
}
static void
-flood_packets(struct ofproto *ofproto, uint16_t odp_in_port, uint32_t mask,
+flood_packets(struct ofproto *ofproto, uint16_t odp_in_port, ovs_be32 mask,
uint16_t *nf_output_iface, struct ofpbuf *odp_actions)
{
struct ofport *ofport;
}
break;
case OFPP_FLOOD:
- flood_packets(ctx->ofproto, ctx->flow.in_port, OFPPC_NO_FLOOD,
+ flood_packets(ctx->ofproto, ctx->flow.in_port, htonl(OFPPC_NO_FLOOD),
&ctx->nf_output_iface, ctx->odp_actions);
break;
case OFPP_ALL:
- flood_packets(ctx->ofproto, ctx->flow.in_port, 0,
+ flood_packets(ctx->ofproto, ctx->flow.in_port, htonl(0),
&ctx->nf_output_iface, ctx->odp_actions);
break;
case OFPP_CONTROLLER:
const struct ofport *port;
port = get_port(ctx->ofproto, ctx->flow.in_port);
- if (port && port->opp.config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP) &&
+ if (port && port->opp.config & htonl(OFPPC_NO_RECV | OFPPC_NO_RECV_STP) &&
port->opp.config & (eth_addr_equals(ctx->flow.dl_dst, eth_addr_stp)
- ? OFPPC_NO_RECV_STP : OFPPC_NO_RECV)) {
+ ? htonl(OFPPC_NO_RECV_STP)
+ : htonl(OFPPC_NO_RECV))) {
/* Drop this flow. */
return;
}
*
* The log message mentions 'msg_type'. */
static int
-reject_slave_controller(struct ofconn *ofconn, const const char *msg_type)
+reject_slave_controller(struct ofconn *ofconn, const char *msg_type)
{
if (ofconn_get_type(ofconn) == OFCONN_PRIMARY
&& ofconn_get_role(ofconn) == NX_ROLE_SLAVE) {
static void
update_port_config(struct ofproto *p, struct ofport *port,
- uint32_t config, uint32_t mask)
+ ovs_be32 config, ovs_be32 mask)
{
mask &= config ^ port->opp.config;
- if (mask & OFPPC_PORT_DOWN) {
- if (config & OFPPC_PORT_DOWN) {
+ if (mask & htonl(OFPPC_PORT_DOWN)) {
+ if (config & htonl(OFPPC_PORT_DOWN)) {
netdev_turn_flags_off(port->netdev, NETDEV_UP, true);
} else {
netdev_turn_flags_on(port->netdev, NETDEV_UP, true);
}
#define REVALIDATE_BITS (OFPPC_NO_RECV | OFPPC_NO_RECV_STP | \
OFPPC_NO_FWD | OFPPC_NO_FLOOD)
- if (mask & REVALIDATE_BITS) {
+ if (mask & htonl(REVALIDATE_BITS)) {
COVERAGE_INC(ofproto_costly_flags);
- port->opp.config ^= mask & REVALIDATE_BITS;
+ port->opp.config ^= mask & htonl(REVALIDATE_BITS);
p->need_revalidate = true;
}
#undef REVALIDATE_BITS
- if (mask & OFPPC_NO_PACKET_IN) {
- port->opp.config ^= OFPPC_NO_PACKET_IN;
+ if (mask & htonl(OFPPC_NO_PACKET_IN)) {
+ port->opp.config ^= htonl(OFPPC_NO_PACKET_IN);
}
}
} else if (memcmp(port->opp.hw_addr, opm->hw_addr, OFP_ETH_ALEN)) {
return ofp_mkerr(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_HW_ADDR);
} else {
- update_port_config(p, port, ntohl(opm->config), ntohl(opm->mask));
+ update_port_config(p, port, opm->config, opm->mask);
if (opm->advertise) {
netdev_set_advertisements(port->netdev, ntohl(opm->advertise));
}
ots = append_ofp_stats_reply(sizeof *ots, ofconn, &msg);
memset(ots, 0, sizeof *ots);
strcpy(ots->name, "classifier");
- ots->wildcards = (ofconn_get_flow_format(ofconn) == NXFF_OPENFLOW10
- ? htonl(OFPFW_ALL) : htonl(OVSFW_ALL));
+ ots->wildcards = htonl(OFPFW_ALL);
ots->max_entries = htonl(1024 * 1024); /* An arbitrary big number. */
ots->active_count = htonl(classifier_count(&p->cls));
put_32aligned_be64(&ots->lookup_count, htonll(0)); /* XXX */
netdev_get_stats(port->netdev, &stats);
ops = append_ofp_stats_reply(sizeof *ops, ofconn, msgp);
- ops->port_no = htons(port->opp.port_no);
+ ops->port_no = port->opp.port_no;
memset(ops->pad, 0, sizeof ops->pad);
put_32aligned_be64(&ops->rx_packets, htonll(stats.rx_packets));
put_32aligned_be64(&ops->tx_packets, htonll(stats.tx_packets));
{
struct ofp_flow_stats *ofs;
uint64_t packet_count, byte_count;
- ovs_be64 cookie;
size_t act_len, len;
if (rule_is_hidden(rule) || !rule_has_out_port(rule, out_port)) {
ofs->length = htons(len);
ofs->table_id = 0;
ofs->pad = 0;
- ofputil_cls_rule_to_match(&rule->cr, ofconn_get_flow_format(ofconn),
- &ofs->match, rule->flow_cookie, &cookie);
- put_32aligned_be64(&ofs->cookie, cookie);
+ ofputil_cls_rule_to_match(&rule->cr, &ofs->match);
+ put_32aligned_be64(&ofs->cookie, rule->flow_cookie);
calc_flow_duration(rule->created, &ofs->duration_sec, &ofs->duration_nsec);
ofs->priority = htons(rule->cr.priority);
ofs->idle_timeout = htons(rule->idle_timeout);
struct cls_rule target;
struct rule *rule;
- ofputil_cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0,
- &target);
+ ofputil_cls_rule_from_match(&fsr->match, 0, &target);
cls_cursor_init(&cursor, &ofproto->cls, &target);
CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
put_ofp_flow_stats(ofconn, rule, fsr->out_port, &reply);
struct cls_rule target;
struct ofpbuf *msg;
- ofputil_cls_rule_from_match(&request->match, 0, NXFF_OPENFLOW10, 0,
- &target);
+ ofputil_cls_rule_from_match(&request->match, 0, &target);
msg = start_ofp_stats_reply(oh, sizeof *reply);
reply = append_ofp_stats_reply(sizeof *reply, ofconn, &msg);
struct ofp_queue_stats *reply;
reply = append_ofp_stats_reply(sizeof *reply, cbdata->ofconn, &cbdata->msg);
- reply->port_no = htons(cbdata->ofport->opp.port_no);
+ reply->port_no = cbdata->ofport->opp.port_no;
memset(reply->pad, 0, sizeof reply->pad);
reply->queue_id = htonl(queue_id);
put_32aligned_be64(&reply->tx_bytes, htonll(stats->tx_bytes));
return error;
}
- error = ofputil_decode_flow_mod(&fm, oh, ofconn_get_flow_format(ofconn));
+ error = ofputil_decode_flow_mod(&fm, oh);
if (error) {
return error;
}
}
}
-static int
-handle_tun_id_from_cookie(struct ofconn *ofconn, const struct ofp_header *oh)
-{
- const struct nxt_tun_id_cookie *msg
- = (const struct nxt_tun_id_cookie *) oh;
- enum nx_flow_format flow_format;
-
- flow_format = msg->set ? NXFF_TUN_ID_FROM_COOKIE : NXFF_OPENFLOW10;
- ofconn_set_flow_format(ofconn, flow_format);
-
- return 0;
-}
-
static int
handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh)
{
format = ntohl(msg->format);
if (format == NXFF_OPENFLOW10
- || format == NXFF_TUN_ID_FROM_COOKIE
|| format == NXFF_NXM) {
ofconn_set_flow_format(ofconn, format);
return 0;
return 0;
/* Nicira extension requests. */
- case OFPUTIL_NXT_TUN_ID_FROM_COOKIE:
- return handle_tun_id_from_cookie(ofconn, oh);
-
case OFPUTIL_NXT_ROLE_REQUEST:
return handle_role_request(ofconn, oh);
/* Check with in-band control to see if this packet should be sent
* to the local port regardless of the flow table. */
if (connmgr_msg_in_hook(p->connmgr, &flow, upcall->packet)) {
- ofproto_send_packet(p, ODPP_LOCAL, 0, upcall->packet);
+ ofproto_send_packet(p, ODPP_LOCAL, upcall->packet);
}
facet = facet_lookup_valid(p, &flow);
/* Don't send a packet-in if OFPPC_NO_PACKET_IN asserted. */
struct ofport *port = get_port(p, flow.in_port);
if (port) {
- if (port->opp.config & OFPPC_NO_PACKET_IN) {
+ if (port->opp.config & htonl(OFPPC_NO_PACKET_IN)) {
COVERAGE_INC(ofproto_no_packet_in);
/* XXX install 'drop' flow entry */
ofpbuf_delete(upcall->packet);
send_packet_in(struct ofproto *ofproto, struct dpif_upcall *upcall,
const struct flow *flow, bool clone)
{
- struct ofputil_packet_in pin;
-
- pin.packet = upcall->packet;
- pin.in_port = odp_port_to_ofp_port(flow->in_port);
- pin.reason = upcall->type == DPIF_UC_MISS ? OFPR_NO_MATCH : OFPR_ACTION;
- pin.buffer_id = 0; /* not yet known */
- pin.send_len = upcall->userdata;
connmgr_send_packet_in(ofproto->connmgr, upcall, flow,
clone ? NULL : upcall->packet);
}
/* Determine output port. */
dst_mac = mac_learning_lookup(ofproto->ml, flow->dl_dst, 0, tags);
if (!dst_mac) {
- flood_packets(ofproto, flow->in_port, OFPPC_NO_FLOOD,
+ flood_packets(ofproto, flow->in_port, htonl(OFPPC_NO_FLOOD),
nf_output_iface, odp_actions);
} else {
int out_port = dst_mac->port.i;