#include "svec.h"
#include "tag.h"
#include "timeval.h"
+#include "unaligned.h"
#include "unixctl.h"
#include "vconn.h"
#include "vlog.h"
* calling action_xlate_ctx_init(). */
void (*resubmit_hook)(struct action_xlate_ctx *, const struct rule *);
+ /* If true, the speciality of 'flow' should be checked before executing
+ * its actions. If special_cb returns false on 'flow' rendered
+ * uninstallable and no actions will be executed. */
+ bool check_special;
+
/* xlate_actions() initializes and uses these members. The client might want
* to look at them after it returns. */
struct ofpbuf *odp_actions;
action_xlate_ctx_init(&ctx, p, flow, packet);
+ /* Always xlate packets originated in this function. */
+ ctx.check_special = false;
odp_actions = xlate_actions(&ctx, actions, n_actions);
/* XXX Should we translate the dpif_execute() errno value into an OpenFlow
return NULL;
}
- ofport = xmalloc(sizeof *ofport);
+ ofport = xzalloc(sizeof *ofport);
ofport->netdev = netdev;
ofport->odp_port = dpif_port->port_no;
ofport->opp.port_no = odp_port_to_ofp_port(dpif_port->port_no);
ctx->flow = *flow;
ctx->packet = packet;
ctx->resubmit_hook = NULL;
+ ctx->check_special = true;
}
static struct ofpbuf *
ctx->nf_output_iface = NF_OUT_DROP;
ctx->recurse = 0;
ctx->last_pop_priority = -1;
- do_xlate_actions(in, n_in, ctx);
+
+ if (!ctx->check_special
+ || (ctx->ofproto->ofhooks->special_cb
+ && ctx->ofproto->ofhooks->special_cb(&ctx->flow, ctx->packet,
+ ctx->ofproto->aux))) {
+ do_xlate_actions(in, n_in, ctx);
+ } else {
+ ctx->may_set_up_flow = false;
+ }
+
remove_pop_action(ctx);
/* Check with in-band control to see if we're allowed to set up this
? htonl(OFPFW_ALL) : htonl(OVSFW_ALL));
ots->max_entries = htonl(1024 * 1024); /* An arbitrary big number. */
ots->active_count = htonl(classifier_count(&p->cls));
- ots->lookup_count = htonll(0); /* XXX */
- ots->matched_count = htonll(0); /* XXX */
+ put_32aligned_be64(&ots->lookup_count, htonll(0)); /* XXX */
+ put_32aligned_be64(&ots->matched_count, htonll(0)); /* XXX */
queue_tx(msg, ofconn, ofconn->reply_counter);
return 0;
ops = append_ofp_stats_reply(sizeof *ops, ofconn, msgp);
ops->port_no = htons(port->opp.port_no);
memset(ops->pad, 0, sizeof ops->pad);
- ops->rx_packets = htonll(stats.rx_packets);
- ops->tx_packets = htonll(stats.tx_packets);
- ops->rx_bytes = htonll(stats.rx_bytes);
- ops->tx_bytes = htonll(stats.tx_bytes);
- ops->rx_dropped = htonll(stats.rx_dropped);
- ops->tx_dropped = htonll(stats.tx_dropped);
- ops->rx_errors = htonll(stats.rx_errors);
- ops->tx_errors = htonll(stats.tx_errors);
- ops->rx_frame_err = htonll(stats.rx_frame_errors);
- ops->rx_over_err = htonll(stats.rx_over_errors);
- ops->rx_crc_err = htonll(stats.rx_crc_errors);
- ops->collisions = htonll(stats.collisions);
+ put_32aligned_be64(&ops->rx_packets, htonll(stats.rx_packets));
+ put_32aligned_be64(&ops->tx_packets, htonll(stats.tx_packets));
+ put_32aligned_be64(&ops->rx_bytes, htonll(stats.rx_bytes));
+ put_32aligned_be64(&ops->tx_bytes, htonll(stats.tx_bytes));
+ put_32aligned_be64(&ops->rx_dropped, htonll(stats.rx_dropped));
+ put_32aligned_be64(&ops->tx_dropped, htonll(stats.tx_dropped));
+ put_32aligned_be64(&ops->rx_errors, htonll(stats.rx_errors));
+ put_32aligned_be64(&ops->tx_errors, htonll(stats.tx_errors));
+ put_32aligned_be64(&ops->rx_frame_err, htonll(stats.rx_frame_errors));
+ put_32aligned_be64(&ops->rx_over_err, htonll(stats.rx_over_errors));
+ put_32aligned_be64(&ops->rx_crc_err, htonll(stats.rx_crc_errors));
+ put_32aligned_be64(&ops->collisions, htonll(stats.collisions));
}
static int
{
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->table_id = 0;
ofs->pad = 0;
ofputil_cls_rule_to_match(&rule->cr, ofconn->flow_format, &ofs->match,
- rule->flow_cookie, &ofs->cookie);
+ rule->flow_cookie, &cookie);
+ put_32aligned_be64(&ofs->cookie, 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);
ofs->hard_timeout = htons(rule->hard_timeout);
memset(ofs->pad2, 0, sizeof ofs->pad2);
- ofs->packet_count = htonll(packet_count);
- ofs->byte_count = htonll(byte_count);
+ put_32aligned_be64(&ofs->packet_count, htonll(packet_count));
+ put_32aligned_be64(&ofs->byte_count, htonll(byte_count));
if (rule->n_actions > 0) {
memcpy(ofs->actions, rule->actions, act_len);
}
}
oasr->flow_count = htonl(n_flows);
- oasr->packet_count = htonll(total_packets);
- oasr->byte_count = htonll(total_bytes);
+ put_32aligned_be64(&oasr->packet_count, htonll(total_packets));
+ put_32aligned_be64(&oasr->byte_count, htonll(total_bytes));
memset(oasr->pad, 0, sizeof oasr->pad);
}
reply->port_no = htons(cbdata->ofport->opp.port_no);
memset(reply->pad, 0, sizeof reply->pad);
reply->queue_id = htonl(queue_id);
- reply->tx_bytes = htonll(stats->tx_bytes);
- reply->tx_packets = htonll(stats->tx_packets);
- reply->tx_errors = htonll(stats->tx_errors);
+ put_32aligned_be64(&reply->tx_bytes, htonll(stats->tx_bytes));
+ put_32aligned_be64(&reply->tx_packets, htonll(stats->tx_packets));
+ put_32aligned_be64(&reply->tx_errors, htonll(stats->tx_errors));
}
static void
/* Set header pointers in 'flow'. */
flow_extract(upcall->packet, flow.tun_id, flow.in_port, &flow);
+ if (p->ofhooks->special_cb
+ && !p->ofhooks->special_cb(&flow, upcall->packet, p->aux)) {
+ ofpbuf_delete(upcall->packet);
+ return;
+ }
+
/* 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, upcall->packet)) {
static const struct ofhooks default_ofhooks = {
default_normal_ofhook_cb,
NULL,
+ NULL,
NULL
};