/* OpenFlow. */
static enum ofperr add_flow(struct ofproto *, struct ofconn *,
- const struct ofputil_flow_mod *,
+ struct ofputil_flow_mod *,
const struct ofp_header *);
static void delete_flow__(struct rule *, struct ofopgroup *,
enum ofp_flow_removed_reason);
static bool handle_openflow(struct ofconn *, const struct ofpbuf *);
static enum ofperr handle_flow_mod__(struct ofproto *, struct ofconn *,
- const struct ofputil_flow_mod *,
+ struct ofputil_flow_mod *,
const struct ofp_header *);
static void calc_duration(long long int start, long long int now,
uint32_t *sec, uint32_t *nsec);
error = ofproto->ofproto_class->construct(ofproto);
if (error) {
VLOG_ERR("failed to open datapath %s: %s",
- datapath_name, strerror(error));
+ datapath_name, ovs_strerror(error));
ofproto_destroy__(ofproto);
return error;
}
if (error) {
VLOG_WARN("%s: CFM configuration on port %"PRIu16" (%s) failed (%s)",
ofproto->name, ofp_port, netdev_get_name(ofport->netdev),
- strerror(error));
+ ovs_strerror(error));
}
}
if (error) {
VLOG_WARN("%s: bfd configuration on port %"PRIu16" (%s) failed (%s)",
ofproto->name, ofp_port, netdev_get_name(ofport->netdev),
- strerror(error));
+ ovs_strerror(error));
}
}
error = class->type_run ? class->type_run(datapath_type) : 0;
if (error && error != EAGAIN) {
VLOG_ERR_RL(&rl, "%s: type_run failed (%s)",
- datapath_type, strerror(error));
+ datapath_type, ovs_strerror(error));
}
return error;
}
error = class->type_run_fast ? class->type_run_fast(datapath_type) : 0;
if (error && error != EAGAIN) {
VLOG_ERR_RL(&rl, "%s: type_run_fast failed (%s)",
- datapath_type, strerror(error));
+ datapath_type, ovs_strerror(error));
}
return error;
}
error = p->ofproto_class->run(p);
if (error && error != EAGAIN) {
- VLOG_ERR_RL(&rl, "%s: run failed (%s)", p->name, strerror(error));
+ VLOG_ERR_RL(&rl, "%s: run failed (%s)", p->name, ovs_strerror(error));
}
if (p->ofproto_class->port_poll) {
error = p->ofproto_class->run_fast ? p->ofproto_class->run_fast(p) : 0;
if (error && error != EAGAIN) {
VLOG_ERR_RL(&rl, "%s: fastpath run failed (%s)",
- p->name, strerror(error));
+ p->name, ovs_strerror(error));
}
return error;
}
*
* This is a helper function for in-band control and fail-open. */
int
-ofproto_flow_mod(struct ofproto *ofproto, const struct ofputil_flow_mod *fm)
+ofproto_flow_mod(struct ofproto *ofproto, struct ofputil_flow_mod *fm)
{
return handle_flow_mod__(ofproto, NULL, fm, NULL);
}
"cannot be opened (%s)",
ofproto->name,
ofproto_port->name, ofproto_port->ofp_port,
- ofproto_port->name, strerror(error));
+ ofproto_port->name, ovs_strerror(error));
return NULL;
}
error:
VLOG_WARN_RL(&rl, "%s: could not add port %s (%s)",
- p->name, netdev_name, strerror(error));
+ p->name, netdev_name, ovs_strerror(error));
if (ofport) {
ofport_destroy__(ofport);
} else {
return 0;
}
-/* Checks that the 'ofpacts_len' bytes of actions in 'ofpacts' are
- * appropriate for a packet with the prerequisites satisfied by 'flow'.
+/* Checks that the 'ofpacts_len' bytes of actions in 'ofpacts' are appropriate
+ * for a packet with the prerequisites satisfied by 'flow' in table 'table_id'.
* 'flow' may be temporarily modified, but is restored at return.
*/
static enum ofperr
ofproto_check_ofpacts(struct ofproto *ofproto,
const struct ofpact ofpacts[], size_t ofpacts_len,
- struct flow *flow)
+ struct flow *flow, uint8_t table_id)
{
enum ofperr error;
uint32_t mid;
- error = ofpacts_check(ofpacts, ofpacts_len, flow, ofproto->max_ports);
+ error = ofpacts_check(ofpacts, ofpacts_len, flow, ofproto->max_ports,
+ table_id);
if (error) {
return error;
}
/* Verify actions against packet, then send packet if successful. */
in_port_.ofp_port = po.in_port;
flow_extract(payload, 0, 0, NULL, &in_port_, &flow);
- error = ofproto_check_ofpacts(p, po.ofpacts, po.ofpacts_len, &flow);
+ error = ofproto_check_ofpacts(p, po.ofpacts, po.ofpacts_len, &flow, 0);
if (!error) {
error = p->ofproto_class->packet_out(p, payload, &flow,
po.ofpacts, po.ofpacts_len);
* if any. */
static enum ofperr
add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
- const struct ofputil_flow_mod *fm, const struct ofp_header *request)
+ struct ofputil_flow_mod *fm, const struct ofp_header *request)
{
struct oftable *table;
struct ofopgroup *group;
return OFPERR_OFPBRC_EPERM;
}
+ /* Verify actions. */
+ error = ofproto_check_ofpacts(ofproto, fm->ofpacts, fm->ofpacts_len,
+ &fm->match.flow, table_id);
+ if (error) {
+ return error;
+ }
+
/* Allocate new rule and initialize classifier rule. */
rule = ofproto->ofproto_class->rule_alloc();
if (!rule) {
VLOG_WARN_RL(&rl, "%s: failed to create rule (%s)",
- ofproto->name, strerror(error));
+ ofproto->name, ovs_strerror(error));
return ENOMEM;
}
cls_rule_init(&rule->cr, &fm->match, fm->priority);
* Returns 0 on success, otherwise an OpenFlow error code. */
static enum ofperr
modify_flows__(struct ofproto *ofproto, struct ofconn *ofconn,
- const struct ofputil_flow_mod *fm,
- const struct ofp_header *request,
+ struct ofputil_flow_mod *fm, const struct ofp_header *request,
struct list *rules)
{
struct ofopgroup *group;
continue;
}
+ /* Verify actions. */
+ error = ofpacts_check(fm->ofpacts, fm->ofpacts_len, &fm->match.flow,
+ ofproto->max_ports, rule->table_id);
+ if (error) {
+ return error;
+ }
+
actions_changed = !ofpacts_equal(fm->ofpacts, fm->ofpacts_len,
rule->ofpacts, rule->ofpacts_len);
static enum ofperr
modify_flows_add(struct ofproto *ofproto, struct ofconn *ofconn,
- const struct ofputil_flow_mod *fm,
- const struct ofp_header *request)
+ struct ofputil_flow_mod *fm, const struct ofp_header *request)
{
if (fm->cookie_mask != htonll(0) || fm->new_cookie == htonll(UINT64_MAX)) {
return 0;
* if any. */
static enum ofperr
modify_flows_loose(struct ofproto *ofproto, struct ofconn *ofconn,
- const struct ofputil_flow_mod *fm,
+ struct ofputil_flow_mod *fm,
const struct ofp_header *request)
{
struct list rules;
* if any. */
static enum ofperr
modify_flow_strict(struct ofproto *ofproto, struct ofconn *ofconn,
- const struct ofputil_flow_mod *fm,
+ struct ofputil_flow_mod *fm,
const struct ofp_header *request)
{
struct list rules;
ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
error = ofputil_decode_flow_mod(&fm, oh, ofconn_get_protocol(ofconn),
&ofpacts);
- if (!error) {
- error = ofproto_check_ofpacts(ofproto, fm.ofpacts, fm.ofpacts_len,
- &fm.match.flow);
- }
-
if (!error) {
error = handle_flow_mod__(ofproto, ofconn, &fm, oh);
}
static enum ofperr
handle_flow_mod__(struct ofproto *ofproto, struct ofconn *ofconn,
- const struct ofputil_flow_mod *fm,
- const struct ofp_header *oh)
+ struct ofputil_flow_mod *fm, const struct ofp_header *oh)
{
if (ofproto->n_pending >= 50) {
ovs_assert(!list_is_empty(&ofproto->pending));
}
VLOG_WARN("%s: could not get MAC address for %s (%s)",
ofproto->name, netdev_get_name(port->netdev),
- strerror(error));
+ ovs_strerror(error));
}
return ofproto->fallback_dpid;
}
if (error) {
VLOG_WARN("%s: setting realdev on port %"PRIu16" (%s) failed (%s)",
ofproto->name, vlandev_ofp_port,
- netdev_get_name(ofport->netdev), strerror(error));
+ netdev_get_name(ofport->netdev), ovs_strerror(error));
}
return error;
}