Rename cls_rule_zero_wildcards() to cls_rule_zero_wildcarded_fields().
[openvswitch] / ofproto / ofproto.c
index 85e8804ab0e59ae438a9c89b7b164d8c95ac8fd2..32ce4f241d811aeca4b0f296dbc586528b842652 100644 (file)
@@ -161,8 +161,7 @@ static void rule_install(struct ofproto *, struct rule *,
                          struct rule *displaced_rule);
 static void rule_uninstall(struct ofproto *, struct rule *);
 static void rule_post_uninstall(struct ofproto *, struct rule *);
-static void send_flow_removed(struct ofproto *p, struct rule *rule,
-                              long long int now, uint8_t reason);
+static void send_flow_removed(struct ofproto *, struct rule *, uint8_t reason);
 
 /* ofproto supports two kinds of OpenFlow connections:
  *
@@ -2866,18 +2865,14 @@ xlate_actions(const union ofp_action *in, size_t n_in,
  * error message code (composed with ofp_mkerr()) for the caller to propagate
  * upward.  Otherwise, returns 0.
  *
- * 'oh' is used to make log messages more informative. */
+ * The log message mentions 'msg_type'. */
 static int
-reject_slave_controller(struct ofconn *ofconn, const struct ofp_header *oh)
+reject_slave_controller(struct ofconn *ofconn, const const char *msg_type)
 {
     if (ofconn->type == OFCONN_PRIMARY && ofconn->role == NX_ROLE_SLAVE) {
         static struct vlog_rate_limit perm_rl = VLOG_RATE_LIMIT_INIT(1, 5);
-        char *type_name;
-
-        type_name = ofp_message_type_to_string(oh->type);
         VLOG_WARN_RL(&perm_rl, "rejecting %s message from slave controller",
-                     type_name);
-        free(type_name);
+                     msg_type);
 
         return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_EPERM);
     } else {
@@ -2897,7 +2892,7 @@ handle_packet_out(struct ofconn *ofconn, struct ofp_header *oh)
     uint16_t in_port;
     int error;
 
-    error = reject_slave_controller(ofconn, oh);
+    error = reject_slave_controller(ofconn, "OFPT_PACKET_OUT");
     if (error) {
         return error;
     }
@@ -2964,7 +2959,7 @@ handle_port_mod(struct ofconn *ofconn, struct ofp_header *oh)
     struct ofport *port;
     int error;
 
-    error = reject_slave_controller(ofconn, oh);
+    error = reject_slave_controller(ofconn, "OFPT_PORT_MOD");
     if (error) {
         return error;
     }
@@ -3197,6 +3192,14 @@ query_stats(struct ofproto *p, struct rule *rule,
     *byte_countp = byte_count;
 }
 
+static void
+calc_flow_duration(long long int start, ovs_be32 *sec, ovs_be32 *nsec)
+{
+    long long int msecs = time_msec() - start;
+    *sec = htonl(msecs / 1000);
+    *nsec = htonl((msecs % 1000) * (1000 * 1000));
+}
+
 static void
 flow_stats_cb(struct cls_rule *rule_, void *cbdata_)
 {
@@ -3205,9 +3208,6 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_)
     struct ofp_flow_stats *ofs;
     uint64_t packet_count, byte_count;
     size_t act_len, len;
-    long long int tdiff = time_msec() - rule->created;
-    uint32_t sec = tdiff / 1000;
-    uint32_t msec = tdiff - (sec * 1000);
 
     if (rule_is_hidden(rule) || !rule_has_out_port(rule, cbdata->out_port)) {
         return;
@@ -3224,8 +3224,7 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_)
     ofs->pad = 0;
     flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards,
                   cbdata->ofconn->flow_format, &ofs->match);
-    ofs->duration_sec = htonl(sec);
-    ofs->duration_nsec = htonl(msec * 1000000);
+    calc_flow_duration(rule->created, &ofs->duration_sec, &ofs->duration_nsec);
     ofs->cookie = rule->flow_cookie;
     ofs->priority = htons(rule->cr.priority);
     ofs->idle_timeout = htons(rule->idle_timeout);
@@ -3353,38 +3352,50 @@ aggregate_stats_cb(struct cls_rule *rule_, void *cbdata_)
     cbdata->n_flows++;
 }
 
+static void
+query_aggregate_stats(struct ofproto *ofproto, struct cls_rule *target,
+                      uint16_t out_port, uint8_t table_id,
+                      struct ofp_aggregate_stats_reply *oasr)
+{
+    struct aggregate_stats_cbdata cbdata;
+
+    COVERAGE_INC(ofproto_agg_request);
+    cbdata.ofproto = ofproto;
+    cbdata.out_port = out_port;
+    cbdata.packet_count = 0;
+    cbdata.byte_count = 0;
+    cbdata.n_flows = 0;
+    classifier_for_each_match(&ofproto->cls, target,
+                              table_id_to_include(table_id),
+                              aggregate_stats_cb, &cbdata);
+
+    oasr->flow_count = htonl(cbdata.n_flows);
+    oasr->packet_count = htonll(cbdata.packet_count);
+    oasr->byte_count = htonll(cbdata.byte_count);
+    memset(oasr->pad, 0, sizeof oasr->pad);
+}
+
 static int
 handle_aggregate_stats_request(struct ofconn *ofconn,
                                const struct ofp_stats_request *osr,
                                size_t arg_size)
 {
-    struct ofp_aggregate_stats_request *asr;
+    struct ofp_aggregate_stats_request *request;
     struct ofp_aggregate_stats_reply *reply;
-    struct aggregate_stats_cbdata cbdata;
     struct cls_rule target;
     struct ofpbuf *msg;
 
-    if (arg_size != sizeof *asr) {
+    if (arg_size != sizeof *request) {
         return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
-    asr = (struct ofp_aggregate_stats_request *) osr->body;
+    request = (struct ofp_aggregate_stats_request *) osr->body;
 
-    COVERAGE_INC(ofproto_agg_request);
-    cbdata.ofproto = ofconn->ofproto;
-    cbdata.out_port = asr->out_port;
-    cbdata.packet_count = 0;
-    cbdata.byte_count = 0;
-    cbdata.n_flows = 0;
-    cls_rule_from_match(&asr->match, 0, NXFF_OPENFLOW10, 0, &target);
-    classifier_for_each_match(&ofconn->ofproto->cls, &target,
-                              table_id_to_include(asr->table_id),
-                              aggregate_stats_cb, &cbdata);
+    cls_rule_from_match(&request->match, 0, NXFF_OPENFLOW10, 0, &target);
 
     msg = start_stats_reply(osr, sizeof *reply);
     reply = append_stats_reply(sizeof *reply, ofconn, &msg);
-    reply->flow_count = htonl(cbdata.n_flows);
-    reply->packet_count = htonll(cbdata.packet_count);
-    reply->byte_count = htonll(cbdata.byte_count);
+    query_aggregate_stats(ofconn->ofproto, &target, request->out_port,
+                          request->table_id, reply);
     queue_tx(msg, ofconn, ofconn->reply_counter);
     return 0;
 }
@@ -3815,7 +3826,7 @@ delete_flow(struct ofproto *p, struct rule *rule, ovs_be16 out_port)
         return;
     }
 
-    send_flow_removed(p, rule, time_msec(), OFPRR_DELETE);
+    send_flow_removed(p, rule, OFPRR_DELETE);
     rule_remove(p, rule);
 }
 \f
@@ -3826,7 +3837,7 @@ handle_flow_mod(struct ofconn *ofconn, struct ofp_flow_mod *ofm)
     size_t n_actions;
     int error;
 
-    error = reject_slave_controller(ofconn, &ofm->header);
+    error = reject_slave_controller(ofconn, "OFPT_FLOW_MOD");
     if (error) {
         return error;
     }
@@ -4460,7 +4471,7 @@ rule_expire(struct cls_rule *cls_rule, void *cbdata_)
 
         /* Get rid of the rule. */
         if (!rule_is_hidden(rule)) {
-            send_flow_removed(cbdata->ofproto, rule, now,
+            send_flow_removed(cbdata->ofproto, rule,
                               (now >= hard_expire
                                ? OFPRR_HARD_TIMEOUT : OFPRR_IDLE_TIMEOUT));
         }
@@ -4512,13 +4523,10 @@ revalidate_rule(struct ofproto *p, struct rule *rule)
 
 static struct ofpbuf *
 compose_flow_removed(struct ofconn *ofconn, const struct rule *rule,
-                     long long int now, uint8_t reason)
+                     uint8_t reason)
 {
     struct ofp_flow_removed *ofr;
     struct ofpbuf *buf;
-    long long int tdiff = now - rule->created;
-    uint32_t sec = tdiff / 1000;
-    uint32_t msec = tdiff - (sec * 1000);
 
     ofr = make_openflow(sizeof *ofr, OFPT_FLOW_REMOVED, &buf);
     flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, ofconn->flow_format,
@@ -4526,8 +4534,7 @@ compose_flow_removed(struct ofconn *ofconn, const struct rule *rule,
     ofr->cookie = rule->flow_cookie;
     ofr->priority = htons(rule->cr.priority);
     ofr->reason = reason;
-    ofr->duration_sec = htonl(sec);
-    ofr->duration_nsec = htonl(msec * 1000000);
+    calc_flow_duration(rule->created, &ofr->duration_sec, &ofr->duration_nsec);
     ofr->idle_timeout = htons(rule->idle_timeout);
     ofr->packet_count = htonll(rule->packet_count);
     ofr->byte_count = htonll(rule->byte_count);
@@ -4536,8 +4543,7 @@ compose_flow_removed(struct ofconn *ofconn, const struct rule *rule,
 }
 
 static void
-send_flow_removed(struct ofproto *p, struct rule *rule,
-                  long long int now, uint8_t reason)
+send_flow_removed(struct ofproto *p, struct rule *rule, uint8_t reason)
 {
     struct ofconn *ofconn;
 
@@ -4553,7 +4559,7 @@ send_flow_removed(struct ofproto *p, struct rule *rule,
             continue;
         }
 
-        msg = compose_flow_removed(ofconn, rule, now, reason);
+        msg = compose_flow_removed(ofconn, rule, reason);
 
         /* Account flow expirations under ofconn->reply_counter, the counter
          * for replies to OpenFlow requests.  That works because preventing