/* ARGSUSED */ static int show_flow_stats(dladm_handle_t handle, dladm_flow_attr_t *attr, void *arg) { show_flow_state_t *state = (show_flow_state_t *)arg; char *name = attr->fa_flowname; pktsum_t stats, diff_stats; flow_args_t fargs; if (state->fs_firstonly) { if (state->fs_donefirst) return (DLADM_WALK_TERMINATE); state->fs_donefirst = B_TRUE; } else { bzero(&state->fs_prevstats, sizeof (state->fs_prevstats)); } get_flow_stats(name, &stats); dladm_stats_diff(&diff_stats, &stats, &state->fs_prevstats); fargs.flow_s_flow = name; fargs.flow_s_psum = &diff_stats; ofmt_print(state->fs_ofmt, (void *)&fargs); state->fs_prevstats = stats; return (DLADM_WALK_CONTINUE); }
static char * parse_dump_flows( char *cmd, const uint64_t own_datapath_id ) { if ( prefixcmp( cmd, "dump_flows" ) ) { return NULL; } char *opt = strchr ( cmd, ' ' ); assert( opt ); uint64_t datapath_val; uint32_t in_port_val; uint16_t eth_type_val; uint8_t ip_proto_val; uint64_t metadata_val[ 2 ]; uint16_t udp_src_val; uint16_t udp_dst_val; uint8_t table_id_val; uint32_t out_port_val; uint32_t out_group_val; uint64_t cookie_val[ 2 ]; struct option opts[] = { OPT_UINT64( "--datapath_id", "datapath_id:", OPT_NO_MASK, &datapath_val ), OPT_UINT32( "--in_port", "in_port:", OPT_NO_MASK, &in_port_val ), OPT_UINT16( "--eth_type", "eth_type:", OPT_NO_MASK, ð_type_val ), OPT_UINT8( "--ip_proto", "ip_proto:", OPT_NO_MASK, &ip_proto_val ), OPT_UINT64( "--metadata", "metadata:", OPT_HAS_MASK, &metadata_val ), OPT_UINT16( "--udp_src", "udp_src:", OPT_NO_MASK, &udp_src_val ), OPT_UINT16( "--udp_dst", "udp_dst:", OPT_NO_MASK, &udp_dst_val ), OPT_UINT8( "--table_id", "table_id:", OPT_NO_MASK, &table_id_val ), OPT_UINT64( "--cookie", "cookie:", OPT_HAS_MASK, &cookie_val ), OPT_UINT32( "--out_port", "out_port:", OPT_NO_MASK, &out_port_val ), OPT_UINT32( "--out_group", "out_group:", OPT_NO_MASK, &out_group_val ), OPT_END() }; char *saveptr; const char *sep = " "; for ( opt = strtok_r( opt, sep, &saveptr ); opt; opt = strtok_r( NULL, sep, &saveptr ) ) { parse_option( opt, opts ); if ( *( uint64_t * ) opts[ 0 ].value != own_datapath_id ) { return NULL; } } match *match = create_match(); parse_match( match, opts ); flow_stats *stats = NULL; uint32_t nr_stats; OFDPE ret = get_flow_stats( ( uint8_t ) table_id_val, match, cookie_val[ 0 ], cookie_val[ 1 ], out_port_val, out_group_val, &stats, &nr_stats ); if ( ret != OFDPE_SUCCESS ) { error( "Failed to retrieve flow stats from datapath ( ret = %d ).", ret ); } delete_match( match ); char *reply_buf = xmalloc( PATH_MAX + 1 ); reply_buf[ 0 ] = '\0'; size_t used = 0; int left; const char *term = ","; const char *orig = "{ \"dump_flows\": ["; if ( stats != NULL && nr_stats ) { for ( uint32_t i = 0; i < nr_stats; i++ ) { if ( i != 0 ) { orig = ""; } if ( i == nr_stats - 1 ) { term = "]}"; } left = snprintf( reply_buf + used, PATH_MAX - used, "%s {" DUMP_FLOW_FIELDS "} %s", orig, stats->table_id, stats->duration_sec, stats->priority, stats->idle_timeout, stats->hard_timeout, stats->flags, stats->cookie, stats->packet_count, stats->byte_count, term ); used = ( size_t ) left - used; stats++; } } return reply_buf; }
size_t match_len = 0; if ( ofp_match != NULL ) { match_len = ofp_match->length - offsetof( struct ofp_match, oxm_fields ); // translate the ofp_match to datapath match. const oxm_match_header *hdr = ( const oxm_match_header * ) ofp_match->oxm_fields; while ( match_len > 0 ) { assign_match( flow_match, hdr ); match_len -= ( sizeof( *hdr ) + OXM_LENGTH( *hdr ) ); if ( match_len > 0 ) { hdr = ( const oxm_match_header * ) ( ( const char * ) hdr + sizeof( *hdr ) + OXM_LENGTH( *hdr ) ); } } } flow_stats *stats = NULL; OFDPE ret = get_flow_stats( table_id, flow_match, cookie, cookie_mask, out_port, out_group, &stats, nr_stats ); if ( ret != OFDPE_SUCCESS ) { error( "Failed to retrieve flow stats from datapath ( ret = %d ).", ret ); } delete_match( flow_match ); return stats; } static uint16_t bucket_list_length( bucket_list **list ) { if ( *list == NULL ) { return 0; } uint16_t length = 0;