@@ -134,9 +134,16 @@ struct ofmirror {
134134 struct ofbundle * out ; /* Output port or NULL. */
135135 int out_vlan ; /* Output VLAN or -1. */
136136 mirror_mask_t dup_mirrors ; /* Bitmap of mirrors with the same output. */
137+
138+ /* Counters. */
139+ int64_t packet_count ; /* Number of packets sent. */
140+ int64_t byte_count ; /* Number of bytes sent. */
137141};
138142
139143static void mirror_destroy (struct ofmirror * );
144+ static void update_mirror_stats (struct ofproto_dpif * ofproto ,
145+ mirror_mask_t mirrors ,
146+ uint64_t packets , uint64_t bytes );
140147
141148/* A group of one or more OpenFlow ports. */
142149#define OFBUNDLE_FLOOD ((struct ofbundle *) 1)
@@ -213,6 +220,7 @@ struct action_xlate_ctx {
213220 bool has_learn ; /* Actions include NXAST_LEARN? */
214221 bool has_normal ; /* Actions output to OFPP_NORMAL? */
215222 uint16_t nf_output_iface ; /* Output interface index for NetFlow. */
223+ mirror_mask_t mirrors ; /* Bitmap of associated mirrors. */
216224
217225/* xlate_actions() initializes and uses these members, but the client has no
218226 * reason to look at them. */
@@ -276,9 +284,9 @@ struct facet {
276284 uint64_t byte_count ; /* Number of bytes received. */
277285
278286 /* Resubmit statistics. */
279- uint64_t rs_packet_count ; /* Packets pushed to resubmit children . */
280- uint64_t rs_byte_count ; /* Bytes pushed to resubmit children . */
281- long long int rs_used ; /* Used time pushed to resubmit children . */
287+ uint64_t prev_packet_count ; /* Number of packets from last stats push . */
288+ uint64_t prev_byte_count ; /* Number of bytes from last stats push . */
289+ long long int prev_used ; /* Used time from last stats push . */
282290
283291 /* Accounting. */
284292 uint64_t accounted_bytes ; /* Bytes processed by facet_account(). */
@@ -294,6 +302,7 @@ struct facet {
294302 bool has_learn ; /* Actions include NXAST_LEARN? */
295303 bool has_normal ; /* Actions output to OFPP_NORMAL? */
296304 tag_type tags ; /* Tags that would require revalidation. */
305+ mirror_mask_t mirrors ; /* Bitmap of dependent mirrors. */
297306};
298307
299308static struct facet * facet_create (struct rule_dpif * , const struct flow * );
@@ -2034,6 +2043,24 @@ mirror_destroy(struct ofmirror *mirror)
20342043 mirror_update_dups (ofproto );
20352044}
20362045
2046+ static int
2047+ mirror_get_stats (struct ofproto * ofproto_ , void * aux ,
2048+ uint64_t * packets , uint64_t * bytes )
2049+ {
2050+ struct ofproto_dpif * ofproto = ofproto_dpif_cast (ofproto_ );
2051+ struct ofmirror * mirror = mirror_lookup (ofproto , aux );
2052+
2053+ if (!mirror ) {
2054+ * packets = * bytes = UINT64_MAX ;
2055+ return 0 ;
2056+ }
2057+
2058+ * packets = mirror -> packet_count ;
2059+ * bytes = mirror -> byte_count ;
2060+
2061+ return 0 ;
2062+ }
2063+
20372064static int
20382065set_flood_vlans (struct ofproto * ofproto_ , unsigned long * flood_vlans )
20392066{
@@ -3271,6 +3298,7 @@ facet_revalidate(struct ofproto_dpif *ofproto, struct facet *facet)
32713298 facet -> may_install = ctx .may_set_up_flow ;
32723299 facet -> has_learn = ctx .has_learn ;
32733300 facet -> has_normal = ctx .has_normal ;
3301+ facet -> mirrors = ctx .mirrors ;
32743302 if (new_actions ) {
32753303 i = 0 ;
32763304 LIST_FOR_EACH (subfacet , list_node , & facet -> subfacets ) {
@@ -3289,7 +3317,7 @@ facet_revalidate(struct ofproto_dpif *ofproto, struct facet *facet)
32893317 list_push_back (& new_rule -> facets , & facet -> list_node );
32903318 facet -> rule = new_rule ;
32913319 facet -> used = new_rule -> up .created ;
3292- facet -> rs_used = facet -> used ;
3320+ facet -> prev_used = facet -> used ;
32933321 }
32943322
32953323 return true;
@@ -3315,30 +3343,33 @@ facet_reset_counters(struct facet *facet)
33153343{
33163344 facet -> packet_count = 0 ;
33173345 facet -> byte_count = 0 ;
3318- facet -> rs_packet_count = 0 ;
3319- facet -> rs_byte_count = 0 ;
3346+ facet -> prev_packet_count = 0 ;
3347+ facet -> prev_byte_count = 0 ;
33203348 facet -> accounted_bytes = 0 ;
33213349}
33223350
33233351static void
33243352facet_push_stats (struct facet * facet )
33253353{
3326- uint64_t rs_packets , rs_bytes ;
3354+ uint64_t new_packets , new_bytes ;
33273355
3328- assert (facet -> packet_count >= facet -> rs_packet_count );
3329- assert (facet -> byte_count >= facet -> rs_byte_count );
3330- assert (facet -> used >= facet -> rs_used );
3356+ assert (facet -> packet_count >= facet -> prev_packet_count );
3357+ assert (facet -> byte_count >= facet -> prev_byte_count );
3358+ assert (facet -> used >= facet -> prev_used );
33313359
3332- rs_packets = facet -> packet_count - facet -> rs_packet_count ;
3333- rs_bytes = facet -> byte_count - facet -> rs_byte_count ;
3360+ new_packets = facet -> packet_count - facet -> prev_packet_count ;
3361+ new_bytes = facet -> byte_count - facet -> prev_byte_count ;
33343362
3335- if (rs_packets || rs_bytes || facet -> used > facet -> rs_used ) {
3336- facet -> rs_packet_count = facet -> packet_count ;
3337- facet -> rs_byte_count = facet -> byte_count ;
3338- facet -> rs_used = facet -> used ;
3363+ if (new_packets || new_bytes || facet -> used > facet -> prev_used ) {
3364+ facet -> prev_packet_count = facet -> packet_count ;
3365+ facet -> prev_byte_count = facet -> byte_count ;
3366+ facet -> prev_used = facet -> used ;
33393367
33403368 flow_push_stats (facet -> rule , & facet -> flow ,
3341- rs_packets , rs_bytes , facet -> used );
3369+ new_packets , new_bytes , facet -> used );
3370+
3371+ update_mirror_stats (ofproto_dpif_cast (facet -> rule -> up .ofproto ),
3372+ facet -> mirrors , new_packets , new_bytes );
33423373 }
33433374}
33443375
@@ -3362,7 +3393,7 @@ push_resubmit(struct action_xlate_ctx *ctx, struct rule_dpif *rule)
33623393}
33633394
33643395/* Pushes flow statistics to the rules which 'flow' resubmits into given
3365- * 'rule''s actions. */
3396+ * 'rule''s actions and mirrors . */
33663397static void
33673398flow_push_stats (const struct rule_dpif * rule ,
33683399 const struct flow * flow , uint64_t packets , uint64_t bytes ,
@@ -3516,6 +3547,7 @@ subfacet_make_actions(struct ofproto_dpif *p, struct subfacet *subfacet,
35163547 facet -> has_learn = ctx .has_learn ;
35173548 facet -> has_normal = ctx .has_normal ;
35183549 facet -> nf_flow .output_iface = ctx .nf_output_iface ;
3550+ facet -> mirrors = ctx .mirrors ;
35193551
35203552 if (subfacet -> actions_len != odp_actions -> size
35213553 || memcmp (subfacet -> actions , odp_actions -> data , odp_actions -> size )) {
@@ -4700,6 +4732,7 @@ xlate_actions(struct action_xlate_ctx *ctx,
47004732 ctx -> has_learn = false;
47014733 ctx -> has_normal = false;
47024734 ctx -> nf_output_iface = NF_OUT_DROP ;
4735+ ctx -> mirrors = 0 ;
47034736 ctx -> recurse = 0 ;
47044737 ctx -> original_priority = ctx -> flow .priority ;
47054738 ctx -> table_id = 0 ;
@@ -5017,6 +5050,7 @@ output_mirrors(struct action_xlate_ctx *ctx,
50175050 }
50185051
50195052 mirrors &= ~m -> dup_mirrors ;
5053+ ctx -> mirrors |= m -> dup_mirrors ;
50205054 if (m -> out ) {
50215055 output_normal (ctx , m -> out , vlan );
50225056 } else if (eth_dst_may_rspan (ctx -> flow .dl_dst )
@@ -5033,6 +5067,34 @@ output_mirrors(struct action_xlate_ctx *ctx,
50335067 }
50345068}
50355069
5070+ static void
5071+ update_mirror_stats (struct ofproto_dpif * ofproto , mirror_mask_t mirrors ,
5072+ uint64_t packets , uint64_t bytes )
5073+ {
5074+ if (!mirrors ) {
5075+ return ;
5076+ }
5077+
5078+ for (; mirrors ; mirrors &= mirrors - 1 ) {
5079+ struct ofmirror * m ;
5080+
5081+ m = ofproto -> mirrors [mirror_mask_ffs (mirrors ) - 1 ];
5082+
5083+ if (!m ) {
5084+ /* In normal circumstances 'm' will not be NULL. However,
5085+ * if mirrors are reconfigured, we can temporarily get out
5086+ * of sync in facet_revalidate(). We could "correct" the
5087+ * mirror list before reaching here, but doing that would
5088+ * not properly account the traffic stats we've currently
5089+ * accumulated for previous mirror configuration. */
5090+ continue ;
5091+ }
5092+
5093+ m -> packet_count += packets ;
5094+ m -> byte_count += bytes ;
5095+ }
5096+ }
5097+
50365098/* A VM broadcasts a gratuitous ARP to indicate that it has resumed after
50375099 * migration. Older Citrix-patched Linux DomU used gratuitous ARP replies to
50385100 * indicate this; newer upstream kernels use gratuitous ARP requests. */
@@ -5964,6 +6026,7 @@ const struct ofproto_class ofproto_dpif_class = {
59646026 bundle_set ,
59656027 bundle_remove ,
59666028 mirror_set ,
6029+ mirror_get_stats ,
59676030 set_flood_vlans ,
59686031 is_mirror_output_bundle ,
59696032 forward_bpdu_changed ,
0 commit comments