static void ofopgroup_destroy(struct ofopgroup *);
-static int add_flow(struct ofproto *, struct ofconn *, struct flow_mod *,
- const struct ofp_header *);
+static int add_flow(struct ofproto *, struct ofconn *,
+ struct ofputil_flow_mod *, const struct ofp_header *);
/* This return value tells handle_openflow() that processing of the current
* OpenFlow message must be postponed until some ongoing operations have
struct ofproto **ofprotop)
{
const struct ofproto_class *class;
+ struct classifier *table;
struct ofproto *ofproto;
+ int n_tables;
int error;
*ofprotop = NULL;
ofproto->datapath_id = 0;
ofproto_set_flow_eviction_threshold(ofproto,
OFPROTO_FLOW_EVICTON_THRESHOLD_DEFAULT);
+ ofproto->forward_bpdu = false;
ofproto->fallback_dpid = pick_fallback_dpid();
ofproto->mfr_desc = xstrdup(DEFAULT_MFR_DESC);
ofproto->hw_desc = xstrdup(DEFAULT_HW_DESC);
list_init(&ofproto->pending);
hmap_init(&ofproto->deletions);
- error = ofproto->ofproto_class->construct(ofproto);
+ error = ofproto->ofproto_class->construct(ofproto, &n_tables);
if (error) {
VLOG_ERR("failed to open datapath %s: %s",
datapath_name, strerror(error));
ofproto_destroy__(ofproto);
return error;
}
- assert(ofproto->n_tables > 0);
+
+ assert(n_tables >= 1 && n_tables <= 255);
+ ofproto->n_tables = n_tables;
+ ofproto->tables = xmalloc(n_tables * sizeof *ofproto->tables);
+ OFPROTO_FOR_EACH_TABLE (table, ofproto) {
+ classifier_init(table);
+ }
ofproto->datapath_id = pick_datapath_id(ofproto);
VLOG_INFO("using datapath ID %016"PRIx64, ofproto->datapath_id);
}
}
+/* If forward_bpdu is true, the NORMAL action will forward frames with
+ * reserved (e.g. STP) destination Ethernet addresses. if forward_bpdu is false,
+ * the NORMAL action will drop these frames. */
+void
+ofproto_set_forward_bpdu(struct ofproto *ofproto, bool forward_bpdu)
+{
+ bool old_val = ofproto->forward_bpdu;
+ ofproto->forward_bpdu = forward_bpdu;
+ if (old_val != ofproto->forward_bpdu) {
+ if (ofproto->ofproto_class->forward_bpdu_changed) {
+ ofproto->ofproto_class->forward_bpdu_changed(ofproto);
+ }
+ }
+}
+
void
ofproto_set_desc(struct ofproto *p,
const char *mfr_desc, const char *hw_desc,
}
group = ofopgroup_create(ofproto);
- for (table = ofproto->tables; table < &ofproto->tables[ofproto->n_tables];
- table++) {
+ OFPROTO_FOR_EACH_TABLE (table, ofproto) {
struct rule *rule, *next_rule;
struct cls_cursor cursor;
static void
ofproto_destroy__(struct ofproto *ofproto)
{
- size_t i;
+ struct classifier *table;
assert(list_is_empty(&ofproto->pending));
hmap_destroy(&ofproto->ports);
shash_destroy(&ofproto->port_by_name);
- for (i = 0; i < ofproto->n_tables; i++) {
- assert(classifier_is_empty(&ofproto->tables[i]));
- classifier_destroy(&ofproto->tables[i]);
+ OFPROTO_FOR_EACH_TABLE (table, ofproto) {
+ assert(classifier_is_empty(table));
+ classifier_destroy(table);
}
free(ofproto->tables);
&ofproto->tables[0], cls_rule));
if (!rule || !ofputil_actions_equal(rule->actions, rule->n_actions,
actions, n_actions)) {
- struct flow_mod fm;
+ struct ofputil_flow_mod fm;
memset(&fm, 0, sizeof fm);
fm.cr = *cls_rule;
ofport_open(const struct ofproto_port *ofproto_port, struct ofp_phy_port *opp)
{
uint32_t curr, advertised, supported, peer;
- struct netdev_options netdev_options;
enum netdev_flags flags;
struct netdev *netdev;
int error;
- memset(&netdev_options, 0, sizeof netdev_options);
- netdev_options.name = ofproto_port->name;
- netdev_options.type = ofproto_port->type;
-
- error = netdev_open(&netdev_options, &netdev);
+ error = netdev_open(ofproto_port->name, ofproto_port->type, &netdev);
if (error) {
VLOG_WARN_RL(&rl, "ignoring port %s (%"PRIu16") because netdev %s "
"cannot be opened (%s)",
const struct ofp_stats_msg *osm)
{
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
- struct flow_stats_request fsr;
+ struct ofputil_flow_stats_request fsr;
struct list replies;
struct list rules;
struct rule *rule;
{
struct classifier *cls;
- for (cls = &p->tables[0]; cls < &p->tables[p->n_tables]; cls++) {
+ OFPROTO_FOR_EACH_TABLE (cls, p) {
struct cls_cursor cursor;
struct rule *rule;
const struct ofp_stats_msg *osm)
{
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
- struct flow_stats_request request;
+ struct ofputil_flow_stats_request request;
struct ofputil_aggregate_stats stats;
bool unknown_packets, unknown_bytes;
struct ofpbuf *reply;
* 'ofconn' is used to retrieve the packet buffer specified in ofm->buffer_id,
* if any. */
static int
-add_flow(struct ofproto *ofproto, struct ofconn *ofconn, struct flow_mod *fm,
- const struct ofp_header *request)
+add_flow(struct ofproto *ofproto, struct ofconn *ofconn,
+ struct ofputil_flow_mod *fm, const struct ofp_header *request)
{
struct classifier *table;
struct ofopgroup *group;
/* Pick table. */
if (fm->table_id == 0xff) {
uint8_t table_id;
- if (ofproto->n_tables > 1) {
+ if (ofproto->ofproto_class->rule_choose_table) {
error = ofproto->ofproto_class->rule_choose_table(ofproto, &fm->cr,
&table_id);
if (error) {
*
* Returns 0 on success, otherwise an OpenFlow error code. */
static int
-modify_flows__(struct ofconn *ofconn, const struct flow_mod *fm,
+modify_flows__(struct ofconn *ofconn, const struct ofputil_flow_mod *fm,
const struct ofp_header *request, struct list *rules)
{
struct ofopgroup *group;
* 'ofconn' is used to retrieve the packet buffer specified in fm->buffer_id,
* if any. */
static int
-modify_flows_loose(struct ofconn *ofconn, struct flow_mod *fm,
+modify_flows_loose(struct ofconn *ofconn, struct ofputil_flow_mod *fm,
const struct ofp_header *request)
{
struct ofproto *p = ofconn_get_ofproto(ofconn);
* 'ofconn' is used to retrieve the packet buffer specified in fm->buffer_id,
* if any. */
static int
-modify_flow_strict(struct ofconn *ofconn, struct flow_mod *fm,
+modify_flow_strict(struct ofconn *ofconn, struct ofputil_flow_mod *fm,
const struct ofp_header *request)
{
struct ofproto *p = ofconn_get_ofproto(ofconn);
/* Implements OFPFC_DELETE. */
static int
-delete_flows_loose(struct ofconn *ofconn, const struct flow_mod *fm,
+delete_flows_loose(struct ofconn *ofconn, const struct ofputil_flow_mod *fm,
const struct ofp_header *request)
{
struct ofproto *p = ofconn_get_ofproto(ofconn);
/* Implements OFPFC_DELETE_STRICT. */
static int
-delete_flow_strict(struct ofconn *ofconn, struct flow_mod *fm,
+delete_flow_strict(struct ofconn *ofconn, struct ofputil_flow_mod *fm,
const struct ofp_header *request)
{
struct ofproto *p = ofconn_get_ofproto(ofconn);
handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
{
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
- struct flow_mod fm;
+ struct ofputil_flow_mod fm;
int error;
error = reject_slave_controller(ofconn, "flow_mod");