action.output.len = htons(sizeof action);
if (in_port == out_port || out_port == DROP) {
/* Set up a flow to drop packets. */
- ofproto_add_flow(ofproto, flow, NULL, 0, NULL, 0);
+ ofproto_add_flow(ofproto, flow, 0, UINT16_MAX, NULL, 0, NULL, 0);
} else if (out_port != FLOOD) {
/* The output port is known, so add a new flow. */
action.output.port = htons(out_port);
- ofproto_add_flow(ofproto, flow, &action, 1, payload, 0);
+ ofproto_add_flow(ofproto, flow, 0, UINT16_MAX, &action, 1, payload, 0);
} else {
/* We don't know that MAC. Send along the packet without setting up a
* flow. */
action.output.len = htons(sizeof action);
if (in_port == out_port || out_port == DROP) {
/* Set up a flow to drop packets. */
- ofproto_add_flow(ofproto, flow, NULL, 0, NULL, 0);
+ ofproto_add_flow(ofproto, flow, 0, UINT16_MAX, NULL, 0, NULL, 0);
} else if (out_port != FLOOD) {
/* The output port is known, so add a new flow. */
action.output.port = htons(out_port);
- ofproto_add_flow(ofproto, flow, &action, 1, payload, 0);
+ ofproto_add_flow(ofproto, flow, 0, UINT16_MAX, &action, 1, payload, 0);
} else {
/* We don't know that MAC. Send along the packet without setting up a
* flow. */
}
void
-ofproto_add_flow(struct ofproto *p, const flow_t *flow,
+ofproto_add_flow(struct ofproto *p,
+ const flow_t *flow, uint32_t wildcards, uint16_t priority,
const union ofp_action *actions, size_t n_actions,
const struct ofpbuf *packet, int idle_timeout)
{
struct odp_flow odp_flow;
rule = xmalloc(sizeof *rule);
- cls_rule_from_flow(&rule->cr, flow, 0, UINT16_MAX);
+ cls_rule_from_flow(&rule->cr, flow, wildcards, priority);
rule->idle_timeout = idle_timeout ? idle_timeout : 5; /* XXX */
rule->hard_timeout = 0; /* XXX */
rule->used = rule->created = time_msec();
rule_destroy(displaced_rule);
}
- rule_make_actions(p, rule, &odp_actions);
- if (packet) {
- if (!ofproto_send_packet(p, flow, actions, n_actions, packet)) {
- rule->byte_count = packet->size;
- rule->packet_count++;
+ if (!wildcards) {
+ rule_make_actions(p, rule, &odp_actions);
+ if (packet) {
+ if (!ofproto_send_packet(p, flow, actions, n_actions, packet)) {
+ rule->byte_count = packet->size;
+ rule->packet_count++;
+ }
}
- }
- memset(&odp_flow.stats, 0, sizeof odp_flow.stats);
- odp_flow.key = *flow;
- odp_flow.actions = odp_actions.actions;
- odp_flow.n_actions = odp_actions.n_actions;
- dpif_flow_add(&p->dpif, &odp_flow);
- odp_actions_free(&odp_actions);
+ memset(&odp_flow.stats, 0, sizeof odp_flow.stats);
+ odp_flow.key = *flow;
+ odp_flow.actions = odp_actions.actions;
+ odp_flow.n_actions = odp_actions.n_actions;
+ dpif_flow_add(&p->dpif, &odp_flow);
+ odp_actions_free(&odp_actions);
+ } else {
+ assert(!packet);
+ }
}
void
}
void
-ofproto_delete_flow(struct ofproto *ofproto, const flow_t *flow)
+ofproto_delete_flow(struct ofproto *ofproto, const flow_t *flow,
+ uint32_t wildcards, uint16_t priority)
{
struct rule *rule;
- rule = rule_from_cls_rule(classifier_lookup_exact(&ofproto->cls, flow));
+ rule = rule_from_cls_rule(classifier_find_rule_exactly(&ofproto->cls,
+ flow, wildcards,
+ priority));
if (rule) {
classifier_remove(&ofproto->cls, &rule->cr);
rule_destroy(rule);
int ofproto_send_packet(struct ofproto *, const flow_t *,
const union ofp_action *, size_t n_actions,
const struct ofpbuf *);
-void ofproto_add_flow(struct ofproto *, const flow_t *,
+void ofproto_add_flow(struct ofproto *,
+ const flow_t *, uint32_t wildcards, uint16_t priority,
const union ofp_action *, size_t n_actions,
const struct ofpbuf *, int idle_timeout);
void ofproto_set_actions(struct ofproto *, const flow_t *,
const union ofp_action *, size_t n_actions);
-void ofproto_delete_flow(struct ofproto *, const flow_t *);
+void ofproto_delete_flow(struct ofproto *, const flow_t *, uint32_t wildcards,
+ uint16_t priority);
/* Hooks for vswitchd. */
struct ofhooks {
n_actions = abuf.size / sizeof(union ofp_action);
if (command == ADD_FLOW) {
- ofproto_add_flow(br->ofproto, &odp_flow, abuf.data, n_actions,
+ ofproto_add_flow(br->ofproto, &odp_flow, 0, UINT16_MAX,
+ abuf.data, n_actions,
pkt, bridge_idle_time(br));
pkt = NULL; /* Already sent. */
* awkward copy). */
odp_flow = *flow;
odp_flow.in_port = ofp_port_to_odp_port(odp_flow.in_port);
- ofproto_add_flow(br->ofproto, &odp_flow, NULL, 0, NULL,
- bridge_idle_time(br));
+ ofproto_add_flow(br->ofproto, &odp_flow, 0, UINT16_MAX,
+ NULL, 0, NULL, bridge_idle_time(br));
if (f) {
ftf_set_dsts(f, NULL, 0);
f->tags = tags;
* awkward copy). */
odp_flow = *flow;
odp_flow.in_port = ofp_port_to_odp_port(odp_flow.in_port);
- ofproto_delete_flow(br->ofproto, &odp_flow);
+ ofproto_delete_flow(br->ofproto, &odp_flow, 0, UINT16_MAX);
/* ofproto_delete_flow() better not call back to
* bridge_flow_expired_ofhook_cb(). */