return retval;
}
+/* Extracts the flow stats for a packet. The 'flow' and 'packet'
+ * arguments must have been initialized through a call to flow_extract().
+ */
+void
+flow_extract_stats(const flow_t *flow, struct ofpbuf *packet,
+ struct odp_flow_stats *stats)
+{
+ memset(stats, '\0', sizeof(*stats));
+
+ if ((flow->dl_type == htons(ETH_TYPE_IP)) && packet->l4) {
+ struct ip_header *ip = packet->l3;
+ stats->ip_tos = ip->ip_tos;
+ if ((flow->nw_proto == IP_TYPE_TCP) && packet->l7) {
+ struct tcp_header *tcp = packet->l4;
+ stats->tcp_flags = TCP_FLAGS(tcp->tcp_ctl);
+ }
+ }
+
+ stats->n_bytes = packet->size;
+ stats->n_packets = 1;
+}
+
void
flow_to_match(const flow_t *flow, uint32_t wildcards, struct ofp_match *match)
{
typedef struct odp_flow_key flow_t;
int flow_extract(struct ofpbuf *, uint16_t in_port, flow_t *);
+void flow_extract_stats(const flow_t *flow, struct ofpbuf *packet,
+ struct odp_flow_stats *stats);
void flow_to_match(const flow_t *, uint32_t wildcards, struct ofp_match *);
void flow_from_match(flow_t *, uint32_t *wildcards, const struct ofp_match *);
char *flow_to_string(const flow_t *);
static int
send_buffered(struct ofproto *p, struct ofconn *ofconn, uint32_t buffer_id,
- const struct rule *rule,
- struct ofpbuf **packetp, int *byte_count)
+ struct rule *rule, struct ofpbuf **packetp)
{
struct odp_actions actions;
struct ofpbuf *packet;
error = dpif_execute(&p->dpif, in_port,
actions.actions, actions.n_actions, packet);
if (!error) {
- *byte_count = packet->size;
+ struct odp_flow_stats stats;
+
+ flow_extract_stats(&flow, packet, &stats);
+ update_stats(rule, &stats);
}
return 0;
cls_rule_from_match(&rule->cr, &ofm->match, ntohs(ofm->priority));
if (ofm->buffer_id != htonl(UINT32_MAX)) {
- int byte_count = 0;
- error = send_buffered(p, ofconn, ntohl(ofm->buffer_id),
- rule, &packet, &byte_count);
- rule->byte_count += byte_count;
- rule->packet_count += byte_count > 0;
+ error = send_buffered(p, ofconn, ntohl(ofm->buffer_id), rule, &packet);
}
displaced_rule = rule_from_cls_rule(classifier_insert(&p->cls, &rule->cr));