{
if (in_band != (p->in_band != NULL)) {
if (in_band) {
- in_band_create(p, p->switch_status, p->controller->rconn,
- &p->in_band);
+ in_band_create(p, &p->dpif, p->switch_status,
+ p->controller->rconn, &p->in_band);
return 0;
} else {
ofproto_set_discovery(p, false, NULL, true);
struct rule *super = rule->super;
rule_account(ofproto, rule, 0);
- if (ofproto->netflow) {
+ if (ofproto->netflow && rule->byte_count) {
struct ofexpired expired;
expired.flow = rule->cr.flow;
expired.packet_count = rule->packet_count;
ctx.tags = tags ? tags : &no_tags;
ctx.may_setup_flow = true;
do_xlate_actions(in, n_in, &ctx);
+
+ /* Check with in-band control to see if we're allowed to setup this
+ * flow. */
+ if (!in_band_rule_check(ofproto->in_band, flow, out)) {
+ ctx.may_setup_flow = false;
+ }
+
if (may_setup_flow) {
*may_setup_flow = ctx.may_setup_flow;
}
}
query_stats(cbdata->ofproto, rule, &packet_count, &byte_count);
- flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, &match);
+ flow_to_ovs_match(&rule->cr.flow, rule->cr.wc.wildcards, &match);
ds_put_format(results, "duration=%llds, ",
(time_msec() - rule->created) / 1000);
- ds_put_format(results, "priority=%u", rule->cr.priority);
+ ds_put_format(results, "priority=%u, ", rule->cr.priority);
ds_put_format(results, "n_packets=%"PRIu64", ", packet_count);
ds_put_format(results, "n_bytes=%"PRIu64", ", byte_count);
ofp_print_match(results, &match, true);
payload.size = msg->length - sizeof *msg;
flow_extract(&payload, msg->port, &flow);
+ /* Check with in-band control to see if this packet should be sent
+ * to the local port regardless of the flow table. */
+ if (in_band_msg_in_hook(p->in_band, &flow, &payload)) {
+ union odp_action action;
+
+ 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);
+ }
+
rule = lookup_valid_rule(p, &flow);
if (!rule) {
/* Don't send a packet-in if OFPPC_NO_PACKET_IN asserted. */
LIST_FOR_EACH (ofconn, struct ofconn, node, &p->all_conns) {
if (ofconn->send_flow_exp && rconn_is_connected(ofconn->rconn)) {
if (prev) {
- queue_tx(ofpbuf_clone(buf), prev, ofconn->reply_counter);
+ queue_tx(ofpbuf_clone(buf), prev, prev->reply_counter);
} else {
buf = compose_flow_exp(rule, now, reason);
}
}
}
if (prev) {
- queue_tx(buf, prev, ofconn->reply_counter);
+ queue_tx(buf, prev, prev->reply_counter);
}
}
do_send_packet_in(struct ofconn *ofconn, uint32_t buffer_id,
const struct ofpbuf *packet, int send_len)
{
- struct ofp_packet_in *opi;
- struct ofpbuf payload, *buf;
- struct odp_msg *msg;
+ struct odp_msg *msg = packet->data;
+ struct ofpbuf payload;
+ struct ofpbuf *opi;
+ uint8_t reason;
- msg = packet->data;
+ /* Extract packet payload from 'msg'. */
payload.data = msg + 1;
payload.size = msg->length - sizeof *msg;
- send_len = MIN(send_len, payload.size);
- buf = ofpbuf_new(sizeof *opi + send_len);
- opi = put_openflow_xid(offsetof(struct ofp_packet_in, data),
- OFPT_PACKET_IN, 0, buf);
- opi->buffer_id = htonl(buffer_id);
- opi->total_len = htons(payload.size);
- opi->in_port = htons(odp_port_to_ofp_port(msg->port));
- opi->reason = msg->type == _ODPL_ACTION_NR ? OFPR_ACTION : OFPR_NO_MATCH;
- ofpbuf_put(buf, payload.data, MIN(send_len, payload.size));
- update_openflow_length(buf);
- rconn_send_with_limit(ofconn->rconn, buf, ofconn->packet_in_counter, 100);
+ /* Construct ofp_packet_in message. */
+ reason = msg->type == _ODPL_ACTION_NR ? OFPR_ACTION : OFPR_NO_MATCH;
+ opi = make_packet_in(buffer_id, odp_port_to_ofp_port(msg->port), reason,
+ &payload, send_len);
+
+ /* Send. */
+ rconn_send_with_limit(ofconn->rconn, opi, ofconn->packet_in_counter, 100);
}
static void