static void hton_ofp_phy_port(struct ofp_phy_port *);
static int xlate_actions(const union ofp_action *in, size_t n_in,
- const flow_t *flow, struct ofproto *ofproto,
+ const struct flow *, struct ofproto *,
const struct ofpbuf *packet,
struct odp_actions *out, tag_type *tags,
bool *may_set_up_flow, uint16_t *nf_output_iface);
static void handle_openflow(struct ofconn *, struct ofproto *,
struct ofpbuf *);
-static void refresh_port_groups(struct ofproto *);
-
static struct ofport *get_port(const struct ofproto *, uint16_t odp_port);
static void update_port(struct ofproto *, const char *devname);
static int init_ports(struct ofproto *);
struct ofport *ofport;
os = ofproto->sflow = ofproto_sflow_create(ofproto->dpif);
- refresh_port_groups(ofproto);
HMAP_FOR_EACH (ofport, hmap_node, &ofproto->ports) {
ofproto_sflow_add_port(os, ofport->odp_port,
netdev_get_name(ofport->netdev));
return error;
}
+/* Checks if 'ofproto' thinks 'odp_port' should be included in floods. Returns
+ * true if 'odp_port' exists and should be included, false otherwise. */
+bool
+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);
+}
+
int
-ofproto_send_packet(struct ofproto *p, const flow_t *flow,
+ofproto_send_packet(struct ofproto *p, const struct flow *flow,
const union ofp_action *actions, size_t n_actions,
const struct ofpbuf *packet)
{
/* XXX Should we translate the dpif_execute() errno value into an OpenFlow
* error code? */
- dpif_execute(p->dpif, flow->in_port, odp_actions.actions,
- odp_actions.n_actions, packet);
+ dpif_execute(p->dpif, odp_actions.actions, odp_actions.n_actions, packet);
return 0;
}
void
-ofproto_add_flow(struct ofproto *p,
- const flow_t *flow, uint32_t wildcards, unsigned int priority,
+ofproto_add_flow(struct ofproto *p, const struct flow *flow,
+ uint32_t wildcards, unsigned int priority,
const union ofp_action *actions, size_t n_actions,
int idle_timeout)
{
}
void
-ofproto_delete_flow(struct ofproto *ofproto, const flow_t *flow,
+ofproto_delete_flow(struct ofproto *ofproto, const struct flow *flow,
uint32_t wildcards, unsigned int priority)
{
struct rule *rule;
svec_destroy(&devnames);
}
-static size_t
-refresh_port_group(struct ofproto *p, unsigned int group)
-{
- uint16_t *ports;
- size_t n_ports;
- struct ofport *port;
-
- assert(group == DP_GROUP_ALL || group == DP_GROUP_FLOOD);
-
- ports = xmalloc(hmap_count(&p->ports) * sizeof *ports);
- n_ports = 0;
- HMAP_FOR_EACH (port, hmap_node, &p->ports) {
- if (group == DP_GROUP_ALL || !(port->opp.config & OFPPC_NO_FLOOD)) {
- ports[n_ports++] = port->odp_port;
- }
- }
- dpif_port_group_set(p->dpif, group, ports, n_ports);
- free(ports);
-
- return n_ports;
-}
-
-static void
-refresh_port_groups(struct ofproto *p)
-{
- size_t n_flood = refresh_port_group(p, DP_GROUP_FLOOD);
- size_t n_all = refresh_port_group(p, DP_GROUP_ALL);
- if (p->sflow) {
- ofproto_sflow_set_group_sizes(p->sflow, n_flood, n_all);
- }
-}
-
static struct ofport *
make_ofport(const struct odp_port *odp_port)
{
: !new_ofport ? OFPPR_DELETE
: OFPPR_MODIFY));
ofport_free(old_ofport);
-
- /* Update port groups. */
- refresh_port_groups(p);
}
static int
}
}
free(ports);
- refresh_port_groups(p);
return 0;
}
\f
} else {
int error;
- error = dpif_execute(ofproto->dpif, in_port,
- actions, n_actions, packet);
+ error = dpif_execute(ofproto->dpif, actions, n_actions, packet);
ofpbuf_delete(packet);
return !error;
}
* Takes ownership of 'packet'. */
static void
rule_execute(struct ofproto *ofproto, struct rule *rule,
- struct ofpbuf *packet, const flow_t *flow)
+ struct ofpbuf *packet, const struct flow *flow)
{
const union odp_action *actions;
struct odp_flow_stats stats;
/* Send the packet and credit it to the rule. */
if (packet) {
- flow_t flow;
+ struct flow flow;
flow_extract(packet, 0, in_port, &flow);
rule_execute(p, rule, packet, &flow);
}
static struct rule *
rule_create_subrule(struct ofproto *ofproto, struct rule *rule,
- const flow_t *flow)
+ const struct flow *flow)
{
struct rule *subrule = rule_create(ofproto, rule, NULL, 0,
rule->idle_timeout, rule->hard_timeout,
struct odp_flow_put *put)
{
memset(&put->flow.stats, 0, sizeof put->flow.stats);
- put->flow.key = rule->cr.flow;
+ odp_flow_key_from_flow(&put->flow.key, &rule->cr.flow);
put->flow.actions = rule->odp_actions;
put->flow.n_actions = rule->n_odp_actions;
put->flow.flags = 0;
if (rule->installed) {
struct odp_flow odp_flow;
- odp_flow.key = rule->cr.flow;
+ odp_flow_key_from_flow(&odp_flow.key, &rule->cr.flow);
odp_flow.actions = NULL;
odp_flow.n_actions = 0;
odp_flow.flags = 0;
return 0;
}
-static void
-add_output_group_action(struct odp_actions *actions, uint16_t group,
- uint16_t *nf_output_iface)
-{
- odp_actions_add(actions, ODPAT_OUTPUT_GROUP)->output_group.group = group;
-
- if (group == DP_GROUP_ALL || group == DP_GROUP_FLOOD) {
- *nf_output_iface = NF_OUT_FLOOD;
- }
-}
-
static void
add_controller_action(struct odp_actions *actions, uint16_t max_len)
{
struct action_xlate_ctx {
/* Input. */
- flow_t flow; /* Flow to which these actions correspond. */
+ struct flow flow; /* Flow to which these actions correspond. */
int recurse; /* Recursion level, via xlate_table_action. */
struct ofproto *ofproto;
const struct ofpbuf *packet; /* The packet corresponding to 'flow', or a
}
static struct rule *
-lookup_valid_rule(struct ofproto *ofproto, const flow_t *flow)
+lookup_valid_rule(struct ofproto *ofproto, const struct flow *flow)
{
struct rule *rule;
rule = rule_from_cls_rule(classifier_lookup(&ofproto->cls, flow));
}
}
+static void
+flood_packets(struct ofproto *ofproto, uint16_t odp_in_port, uint32_t mask,
+ uint16_t *nf_output_iface, struct odp_actions *actions)
+{
+ struct ofport *ofport;
+
+ HMAP_FOR_EACH (ofport, hmap_node, &ofproto->ports) {
+ uint16_t odp_port = ofport->odp_port;
+ if (odp_port != odp_in_port && !(ofport->opp.config & mask)) {
+ odp_actions_add(actions, ODPAT_OUTPUT)->output.port = odp_port;
+ }
+ }
+ *nf_output_iface = NF_OUT_FLOOD;
+}
+
static void
xlate_output_action__(struct action_xlate_ctx *ctx,
uint16_t port, uint16_t max_len)
}
break;
case OFPP_FLOOD:
- add_output_group_action(ctx->out, DP_GROUP_FLOOD,
- &ctx->nf_output_iface);
+ flood_packets(ctx->ofproto, ctx->flow.in_port, OFPPC_NO_FLOOD,
+ &ctx->nf_output_iface, ctx->out);
break;
case OFPP_ALL:
- add_output_group_action(ctx->out, DP_GROUP_ALL, &ctx->nf_output_iface);
+ flood_packets(ctx->ofproto, ctx->flow.in_port, 0,
+ &ctx->nf_output_iface, ctx->out);
break;
case OFPP_CONTROLLER:
add_controller_action(ctx->out, max_len);
break;
case OFPAT_SET_VLAN_VID:
- oa = odp_actions_add(ctx->out, ODPAT_SET_VLAN_VID);
- ctx->flow.dl_vlan = oa->vlan_vid.vlan_vid = ia->vlan_vid.vlan_vid;
+ oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI);
+ oa->dl_tci.tci = ia->vlan_vid.vlan_vid;
+ oa->dl_tci.tci |= htons(ctx->flow.dl_vlan_pcp << VLAN_PCP_SHIFT);
+ ctx->flow.dl_vlan = ia->vlan_vid.vlan_vid;
break;
case OFPAT_SET_VLAN_PCP:
- oa = odp_actions_add(ctx->out, ODPAT_SET_VLAN_PCP);
- ctx->flow.dl_vlan_pcp = oa->vlan_pcp.vlan_pcp = ia->vlan_pcp.vlan_pcp;
+ oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI);
+ oa->dl_tci.tci = htons(ia->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT);
+ oa->dl_tci.tci |= ctx->flow.dl_vlan;
+ ctx->flow.dl_vlan_pcp = ia->vlan_pcp.vlan_pcp;
break;
case OFPAT_STRIP_VLAN:
static int
xlate_actions(const union ofp_action *in, size_t n_in,
- const flow_t *flow, struct ofproto *ofproto,
+ const struct flow *flow, struct ofproto *ofproto,
const struct ofpbuf *packet,
struct odp_actions *out, tag_type *tags, bool *may_set_up_flow,
uint16_t *nf_output_iface)
struct ofp_packet_out *opo;
struct ofpbuf payload, *buffer;
struct odp_actions actions;
+ struct flow flow;
int n_actions;
uint16_t in_port;
- flow_t flow;
int error;
error = reject_slave_controller(ofconn, oh);
return error;
}
- dpif_execute(p->dpif, flow.in_port, actions.actions, actions.n_actions,
- &payload);
+ dpif_execute(p->dpif, actions.actions, actions.n_actions, &payload);
ofpbuf_delete(buffer);
return 0;
netdev_turn_flags_on(port->netdev, NETDEV_UP, true);
}
}
-#define REVALIDATE_BITS (OFPPC_NO_RECV | OFPPC_NO_RECV_STP | OFPPC_NO_FWD)
+#define REVALIDATE_BITS (OFPPC_NO_RECV | OFPPC_NO_RECV_STP | \
+ OFPPC_NO_FWD | OFPPC_NO_FLOOD)
if (mask & REVALIDATE_BITS) {
COVERAGE_INC(ofproto_costly_flags);
port->opp.config ^= mask & REVALIDATE_BITS;
p->need_revalidate = true;
}
#undef REVALIDATE_BITS
- if (mask & OFPPC_NO_FLOOD) {
- port->opp.config ^= OFPPC_NO_FLOOD;
- refresh_port_groups(p);
- }
if (mask & OFPPC_NO_PACKET_IN) {
port->opp.config ^= OFPPC_NO_PACKET_IN;
}
if (rule->cr.wc.wildcards) {
size_t i = 0;
LIST_FOR_EACH (subrule, list, &rule->list) {
- odp_flows[i++].key = subrule->cr.flow;
+ odp_flow_key_from_flow(&odp_flows[i++].key, &subrule->cr.flow);
packet_count += subrule->packet_count;
byte_count += subrule->byte_count;
}
} else {
- odp_flows[0].key = rule->cr.flow;
+ odp_flow_key_from_flow(&odp_flows[0].key, &rule->cr.flow);
}
/* Fetch up-to-date statistics from the datapath and add them in. */
int error;
if (ofm->flags & htons(OFPFF_CHECK_OVERLAP)) {
- flow_t flow;
+ struct flow flow;
uint32_t wildcards;
flow_from_match(&ofm->match, p->tun_id_from_cookie, ofm->cookie,
find_flow_strict(struct ofproto *p, const struct ofp_flow_mod *ofm)
{
uint32_t wildcards;
- flow_t flow;
+ struct flow flow;
flow_from_match(&ofm->match, p->tun_id_from_cookie, ofm->cookie,
&flow, &wildcards);
{
struct ofpbuf *packet;
uint16_t in_port;
- flow_t flow;
+ struct flow flow;
int error;
if (ofm->buffer_id == htonl(UINT32_MAX)) {
struct odp_msg *msg = packet->data;
struct rule *rule;
struct ofpbuf payload;
- flow_t flow;
+ struct flow flow;
payload.data = msg + 1;
payload.size = msg->length - sizeof *msg;
memset(&action, 0, sizeof(action));
action.output.type = ODPAT_OUTPUT;
action.output.port = ODPP_LOCAL;
- dpif_execute(p->dpif, flow.in_port, &action, 1, &payload);
+ dpif_execute(p->dpif, &action, 1, &payload);
}
rule = lookup_valid_rule(p, &flow);
for (i = 0; i < n_flows; i++) {
struct odp_flow *f = &flows[i];
struct rule *rule;
+ struct flow flow;
+
+ odp_flow_key_to_flow(&f->key, &flow);
rule = rule_from_cls_rule(
- classifier_find_rule_exactly(&p->cls, &f->key, 0, UINT16_MAX));
+ classifier_find_rule_exactly(&p->cls, &flow, 0, UINT16_MAX));
if (rule && rule->installed) {
update_time(p, rule, &f->stats);
* ofproto_update_used() zeroed TCP flags. */
memset(&odp_flow, 0, sizeof odp_flow);
if (rule->installed) {
- odp_flow.key = rule->cr.flow;
+ odp_flow_key_from_flow(&odp_flow.key, &rule->cr.flow);
odp_flow.flags = ODPFF_ZERO_TCP_FLAGS;
dpif_flow_get(ofproto->dpif, &odp_flow);
static bool
revalidate_rule(struct ofproto *p, struct rule *rule)
{
- const flow_t *flow = &rule->cr.flow;
+ const struct flow *flow = &rule->cr.flow;
COVERAGE_INC(ofproto_revalidate_rule);
if (rule->super) {
}
\f
static bool
-default_normal_ofhook_cb(const flow_t *flow, const struct ofpbuf *packet,
+default_normal_ofhook_cb(const struct flow *flow, const struct ofpbuf *packet,
struct odp_actions *actions, tag_type *tags,
uint16_t *nf_output_iface, void *ofproto_)
{
out_port = mac_learning_lookup_tag(ofproto->ml, flow->dl_dst, 0, tags,
NULL);
if (out_port < 0) {
- add_output_group_action(actions, DP_GROUP_FLOOD, nf_output_iface);
+ flood_packets(ofproto, flow->in_port, OFPPC_NO_FLOOD,
+ nf_output_iface, actions);
} else if (out_port != flow->in_port) {
odp_actions_add(actions, ODPAT_OUTPUT)->output.port = out_port;
*nf_output_iface = out_port;