ofproto: Add support for flow cookies (OpenFlow 1.0)
[sliver-openvswitch.git] / ofproto / ofproto.c
index d3fd45a..325a11d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -87,6 +87,8 @@ static int xlate_actions(const union ofp_action *in, size_t n_in,
 struct rule {
     struct cls_rule cr;
 
+    uint64_t flow_cookie;       /* Controller-issued identifier. 
+                                   (Kept in network-byte order.) */
     uint16_t idle_timeout;      /* In seconds from time of last use. */
     uint16_t hard_timeout;      /* In seconds from time of creation. */
     bool send_flow_removed;     /* Send a flow removed message? */
@@ -148,7 +150,7 @@ rule_is_hidden(const struct rule *rule)
 static struct rule *rule_create(struct ofproto *, struct rule *super,
                                 const union ofp_action *, size_t n_actions,
                                 uint16_t idle_timeout, uint16_t hard_timeout,
-                                bool send_flow_removed);
+                                uint64_t flow_cookie, bool send_flow_removed);
 static void rule_free(struct rule *);
 static void rule_destroy(struct ofproto *, struct rule *);
 static struct rule *rule_from_cls_rule(const struct cls_rule *);
@@ -194,6 +196,7 @@ struct ofproto {
     char *hardware;             /* Hardware. */
     char *software;             /* Software version. */
     char *serial;               /* Serial number. */
+    char *dp_desc;              /* Datapath description. */
 
     /* Datapath. */
     struct dpif *dpif;
@@ -303,6 +306,7 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux,
     p->hardware = xstrdup("Reference Implementation");
     p->software = xstrdup(VERSION BUILDNR);
     p->serial = xstrdup("None");
+    p->dp_desc = xstrdup("None");
 
     /* Initialize datapath. */
     p->dpif = dpif;
@@ -360,7 +364,7 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux,
 
     /* Pick final datapath ID. */
     p->datapath_id = pick_datapath_id(p);
-    VLOG_INFO("using datapath ID %012"PRIx64, p->datapath_id);
+    VLOG_INFO("using datapath ID %016"PRIx64, p->datapath_id);
 
     *ofprotop = p;
     return 0;
@@ -372,7 +376,7 @@ ofproto_set_datapath_id(struct ofproto *p, uint64_t datapath_id)
     uint64_t old_dpid = p->datapath_id;
     p->datapath_id = datapath_id ? datapath_id : pick_datapath_id(p);
     if (p->datapath_id != old_dpid) {
-        VLOG_INFO("datapath ID changed to %012"PRIx64, p->datapath_id);
+        VLOG_INFO("datapath ID changed to %016"PRIx64, p->datapath_id);
         rconn_reconnect(p->controller->rconn);
     }
 }
@@ -403,7 +407,8 @@ ofproto_set_max_backoff(struct ofproto *p, int max_backoff)
 void
 ofproto_set_desc(struct ofproto *p,
                  const char *manufacturer, const char *hardware,
-                 const char *software, const char *serial)
+                 const char *software, const char *serial,
+                 const char *dp_desc)
 {
     if (manufacturer) {
         free(p->manufacturer);
@@ -421,6 +426,10 @@ ofproto_set_desc(struct ofproto *p,
         free(p->serial);
         p->serial = xstrdup(serial);
     }
+    if (dp_desc) {
+        free(p->dp_desc);
+        p->dp_desc = xstrdup(dp_desc);
+    }
 }
 
 int
@@ -995,7 +1004,7 @@ ofproto_add_flow(struct ofproto *p,
     struct rule *rule;
     rule = rule_create(p, NULL, actions, n_actions,
                        idle_timeout >= 0 ? idle_timeout : 5 /* XXX */, 
-                       0, false);
+                       0, 0, false);
     cls_rule_from_flow(&rule->cr, flow, wildcards, priority);
     rule_insert(p, rule, NULL, 0);
 }
@@ -1390,11 +1399,12 @@ static struct rule *
 rule_create(struct ofproto *ofproto, struct rule *super,
             const union ofp_action *actions, size_t n_actions,
             uint16_t idle_timeout, uint16_t hard_timeout,
-            bool send_flow_removed)
+            uint64_t flow_cookie, bool send_flow_removed)
 {
     struct rule *rule = xcalloc(1, sizeof *rule);
     rule->idle_timeout = idle_timeout;
     rule->hard_timeout = hard_timeout;
+    rule->flow_cookie = flow_cookie;
     rule->used = rule->created = time_msec();
     rule->send_flow_removed = send_flow_removed;
     rule->super = super;
@@ -1557,7 +1567,7 @@ rule_create_subrule(struct ofproto *ofproto, struct rule *rule,
 {
     struct rule *subrule = rule_create(ofproto, rule, NULL, 0,
                                        rule->idle_timeout, rule->hard_timeout,
-                                       false);
+                                       0, false);
     COVERAGE_INC(ofproto_subrule_create);
     cls_rule_from_flow(&subrule->cr, flow, 0,
                        (rule->cr.priority <= UINT16_MAX ? UINT16_MAX
@@ -2378,6 +2388,7 @@ handle_desc_stats_request(struct ofproto *p, struct ofconn *ofconn,
     strncpy(ods->hw_desc, p->hardware, sizeof ods->hw_desc);
     strncpy(ods->sw_desc, p->software, sizeof ods->sw_desc);
     strncpy(ods->serial_num, p->serial, sizeof ods->serial_num);
+    strncpy(ods->dp_desc, p->dp_desc, sizeof ods->dp_desc);
     queue_tx(msg, ofconn, ofconn->reply_counter);
 
     return 0;
@@ -2550,10 +2561,11 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_)
     ofs->pad = 0;
     flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, &ofs->match);
     ofs->duration = htonl((time_msec() - rule->created) / 1000);
+    ofs->cookie = rule->flow_cookie;
     ofs->priority = htons(rule->cr.priority);
     ofs->idle_timeout = htons(rule->idle_timeout);
     ofs->hard_timeout = htons(rule->hard_timeout);
-    ofs->pad2 = 0;
+    memset(ofs->pad2, 0, sizeof ofs->pad2);
     ofs->packet_count = htonll(packet_count);
     ofs->byte_count = htonll(byte_count);
     memcpy(ofs->actions, rule->actions, act_len);
@@ -2804,7 +2816,7 @@ add_flow(struct ofproto *p, struct ofconn *ofconn,
 
     rule = rule_create(p, NULL, (const union ofp_action *) ofm->actions,
                        n_actions, ntohs(ofm->idle_timeout),
-                       ntohs(ofm->hard_timeout),
+                       ntohs(ofm->hard_timeout),  ofm->cookie,
                        ofm->flags & htons(OFPFF_SEND_FLOW_REM));
     cls_rule_from_match(&rule->cr, &ofm->match, ntohs(ofm->priority));
 
@@ -2844,6 +2856,7 @@ modify_flow(struct ofproto *p, const struct ofp_flow_mod *ofm,
         free(rule->actions);
         rule->actions = xmemdup(ofm->actions, actions_len);
         rule->n_actions = n_actions;
+        rule->flow_cookie = ofm->cookie;
 
         if (rule->cr.wc.wildcards) {
             COVERAGE_INC(ofproto_mod_wc_flow);
@@ -3071,6 +3084,19 @@ handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg)
     return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE);
 }
 
+static int
+handle_barrier_request(struct ofconn *ofconn, struct ofp_header *oh)
+{
+    struct ofp_header *ob;
+    struct ofpbuf *buf;
+
+    /* Currently, everything executes synchronously, so we can just
+     * immediately send the barrier reply. */
+    ob = make_openflow_xid(sizeof *ob, OFPT_BARRIER_REPLY, oh->xid, &buf);
+    queue_tx(buf, ofconn, ofconn->reply_counter);
+    return 0;
+}
+
 static void
 handle_openflow(struct ofconn *ofconn, struct ofproto *p,
                 struct ofpbuf *ofp_msg)
@@ -3120,6 +3146,10 @@ handle_openflow(struct ofconn *ofconn, struct ofproto *p,
         error = handle_vendor(p, ofconn, ofp_msg->data);
         break;
 
+    case OFPT_BARRIER_REQUEST:
+        error = handle_barrier_request(ofconn, oh);
+        break;
+
     default:
         if (VLOG_IS_WARN_ENABLED()) {
             char *s = ofp_to_string(oh, ntohs(oh->length), 2);
@@ -3272,6 +3302,7 @@ compose_flow_removed(const struct rule *rule, long long int now, uint8_t reason)
 
     ofr = make_openflow(sizeof *ofr, OFPT_FLOW_REMOVED, &buf);
     flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, &ofr->match);
+    ofr->cookie = rule->flow_cookie;
     ofr->priority = htons(rule->cr.priority);
     ofr->reason = reason;
     ofr->duration = htonl((now - rule->created - last_used) / 1000);