Make "controller nl:0" work again, by fixing a layering violation.
[sliver-openvswitch.git] / datapath / datapath.c
index 4cea5a8..83ef565 100644 (file)
@@ -696,13 +696,6 @@ static void fill_port_desc(struct net_bridge_port *p, struct ofp_phy_port *desc)
        desc->features = 0;
        desc->speed = 0;
 
-       if (p->port_no < 255) {
-               /* FIXME: this is a layering violation and should really be
-                * done in the secchan, as with OFPC_STP in
-                * OFP_SUPPORTED_CAPABILITIES. */
-               desc->features |= OFPPF_STP;
-       }
-
        spin_lock_irqsave(&p->lock, flags);
        desc->flags = htonl(p->flags | p->status);
        spin_unlock_irqrestore(&p->lock, flags);
@@ -798,6 +791,29 @@ dp_send_config_reply(struct datapath *dp, const struct sender *sender)
        return send_openflow_skb(skb, sender);
 }
 
+int
+dp_send_hello(struct datapath *dp, const struct sender *sender,
+             const struct ofp_header *request)
+{
+       if (request->version < OFP_VERSION) {
+               char err[64];
+               sprintf(err, "Only version 0x%02x supported", OFP_VERSION);
+               dp_send_error_msg(dp, sender, OFPET_HELLO_FAILED,
+                                 OFPHFC_INCOMPATIBLE, err, strlen(err));
+               return -EINVAL;
+       } else {
+               struct sk_buff *skb;
+               struct ofp_header *reply;
+
+               reply = alloc_openflow_skb(dp, sizeof *reply,
+                                          OFPT_HELLO, sender, &skb);
+               if (!reply)
+                       return -ENOMEM;
+
+               return send_openflow_skb(skb, sender);
+       }
+}
+
 /* Callback function for a workqueue to disable an interface */
 static void
 down_port_cb(struct work_struct *work)
@@ -953,7 +969,7 @@ dp_send_error_msg(struct datapath *dp, const struct sender *sender,
        struct ofp_error_msg *oem;
 
 
-       oem = alloc_openflow_skb(dp, sizeof(*oem)+len, OFPT_ERROR_MSG
+       oem = alloc_openflow_skb(dp, sizeof(*oem)+len, OFPT_ERROR, 
                        sender, &skb);
        if (!oem)
                return -ENOMEM;
@@ -1249,13 +1265,14 @@ static int flow_stats_init(struct datapath *dp, const void *body, int body_len,
 
 static int flow_stats_dump_callback(struct sw_flow *flow, void *private)
 {
+       struct sw_flow_actions *sf_acts = rcu_dereference(flow->sf_acts);
        struct flow_stats_state *s = private;
        struct ofp_flow_stats *ofs;
        int actions_length;
        int length;
 
-       actions_length = sizeof *ofs->actions * flow->n_actions;
-       length = sizeof *ofs + sizeof *ofs->actions * flow->n_actions;
+       actions_length = sizeof *ofs->actions * sf_acts->n_actions;
+       length = sizeof *ofs + actions_length;
        if (length + s->bytes_used > s->bytes_allocated)
                return 1;
 
@@ -1282,7 +1299,7 @@ static int flow_stats_dump_callback(struct sw_flow *flow, void *private)
        memset(ofs->pad2, 0, sizeof ofs->pad2);
        ofs->packet_count    = cpu_to_be64(flow->packet_count);
        ofs->byte_count      = cpu_to_be64(flow->byte_count);
-       memcpy(ofs->actions, flow->actions, actions_length);
+       memcpy(ofs->actions, sf_acts->actions, actions_length);
 
        s->bytes_used += length;
        return 0;
@@ -1577,7 +1594,8 @@ dp_genl_openflow_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
                        return -EINVAL;
 
                rq = nla_data(va);
-               sender.xid = type = ntohs(rq->type);
+               sender.xid = rq->header.xid;
+               type = ntohs(rq->type);
                if (rq->header.version != OFP_VERSION) {
                        dp_send_error_msg(dp, &sender, OFPET_BAD_REQUEST,
                                          OFPBRC_BAD_VERSION, rq, len);