2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00

sflow: Export LAG, PORTNAME, and OPENFLOWPORT information also.

Export standard sFlow LAG, PORTNAME and OPENFLOWPORT structures with each
counter-sample. Add unit-test for sFlow-LAG. Adjust other unit-tests to
accommodate these new annotations.

The sFlow-LAG structures are important for topology discovery, for
troubleshooting LAG instability,  and for correctly combining
sFlow feeds from multiple sources.

The OPENFLOWPORT and PORTNAME structures are important for systems that
aim to combine sFlow monitoring with OpenFlow controls,  as they
provide straightforward mapping (1) between sFlow agent IP and OpenFlow
datapath-id,  and (2) between interface name,ifIndex and OpenFlow
port number.

Signed-off-by: Neil McKee <neil.mckee@inmon.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Neil McKee 2014-06-27 11:19:59 -07:00 committed by Ben Pfaff
parent afc63bb4bc
commit 50b9699fe4
14 changed files with 534 additions and 5 deletions

2
NEWS
View File

@ -11,6 +11,8 @@ Post-v2.3.0
release. The protocol is documented at
http://tools.ietf.org/html/draft-gross-geneve-00
- The OVS database now reports controller rate limiting statistics.
- sflow now exports information about LACP-based bonds, port names, and
OpenFlow port numbers.
- ovs-dpctl functionality is now available for datapaths integrated
into ovs-vswitchd, via ovs-appctl. Some existing ovs-appctl
commands are now redundant and will be removed in a future

View File

@ -125,6 +125,10 @@ struct slave {
struct lacp_info ntt_actor; /* Used to decide if we Need To Transmit. */
struct timer tx; /* Next message transmission timer. */
struct timer rx; /* Expected message receive timer. */
uint32_t count_rx_pdus; /* dot3adAggPortStatsLACPDUsRx */
uint32_t count_rx_pdus_bad; /* dot3adAggPortStatsIllegalRx */
uint32_t count_tx_pdus; /* dot3adAggPortStatsLACPDUsTx */
};
static struct ovs_mutex mutex;
@ -328,9 +332,11 @@ lacp_process_packet(struct lacp *lacp, const void *slave_,
if (!slave) {
goto out;
}
slave->count_rx_pdus++;
pdu = parse_lacp_packet(packet);
if (!pdu) {
slave->count_rx_pdus_bad++;
VLOG_WARN_RL(&rl, "%s: received an unparsable LACP PDU.", lacp->name);
goto out;
}
@ -548,6 +554,7 @@ lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu) OVS_EXCLUDED(mutex)
slave->ntt_actor = actor;
compose_lacp_pdu(&actor, &slave->partner, &pdu);
send_pdu(slave->aux, &pdu, sizeof pdu);
slave->count_tx_pdus++;
duration = (slave->partner.state & LACP_STATE_TIME
? LACP_FAST_TIME_TX
@ -978,3 +985,58 @@ lacp_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[],
out:
lacp_unlock();
}
/* Extract a snapshot of the current state and counters for a slave port.
Return false if the slave is not active. */
bool
lacp_get_slave_stats(const struct lacp *lacp, const void *slave_, struct lacp_slave_stats *stats)
OVS_EXCLUDED(mutex)
{
struct slave *slave;
struct lacp_info actor;
bool ret;
ovs_mutex_lock(&mutex);
slave = slave_lookup(lacp, slave_);
if (slave) {
ret = true;
slave_get_actor(slave, &actor);
memcpy(&stats->dot3adAggPortActorSystemID,
actor.sys_id,
ETH_ADDR_LEN);
memcpy(&stats->dot3adAggPortPartnerOperSystemID,
slave->partner.sys_id,
ETH_ADDR_LEN);
stats->dot3adAggPortAttachedAggID = (lacp->key_slave->key ?
lacp->key_slave->key :
lacp->key_slave->port_id);
/* Construct my admin-state. Assume aggregation is configured on. */
stats->dot3adAggPortActorAdminState = LACP_STATE_AGG;
if (lacp->active) {
stats->dot3adAggPortActorAdminState |= LACP_STATE_ACT;
}
if (lacp->fast) {
stats->dot3adAggPortActorAdminState |= LACP_STATE_TIME;
}
/* XXX Not sure how to know the partner admin state. It
* might have to be captured and remembered during the
* negotiation phase.
*/
stats->dot3adAggPortPartnerAdminState = 0;
stats->dot3adAggPortActorOperState = actor.state;
stats->dot3adAggPortPartnerOperState = slave->partner.state;
/* Read out the latest counters */
stats->dot3adAggPortStatsLACPDUsRx = slave->count_rx_pdus;
stats->dot3adAggPortStatsIllegalRx = slave->count_rx_pdus_bad;
stats->dot3adAggPortStatsLACPDUsTx = slave->count_tx_pdus;
} else {
ret = false;
}
ovs_mutex_unlock(&mutex);
return ret;
}

View File

@ -70,4 +70,27 @@ typedef void lacp_send_pdu(void *slave, const void *pdu, size_t pdu_size);
void lacp_run(struct lacp *, lacp_send_pdu *);
void lacp_wait(struct lacp *);
struct lacp_slave_stats {
/* id */
uint8_t dot3adAggPortActorSystemID[ETH_ADDR_LEN];
uint8_t dot3adAggPortPartnerOperSystemID[ETH_ADDR_LEN];
uint32_t dot3adAggPortAttachedAggID;
/* state */
uint8_t dot3adAggPortActorAdminState;
uint8_t dot3adAggPortActorOperState;
uint8_t dot3adAggPortPartnerAdminState;
uint8_t dot3adAggPortPartnerOperState;
/* counters */
uint32_t dot3adAggPortStatsLACPDUsRx;
/* uint32_t dot3adAggPortStatsMarkerPDUsRx; */
/* uint32_t dot3adAggPortStatsMarkerResponsePDUsRx; */
/* uint32_t dot3adAggPortStatsUnknownRx; */
uint32_t dot3adAggPortStatsIllegalRx;
uint32_t dot3adAggPortStatsLACPDUsTx;
/* uint32_t dot3adAggPortStatsMarkerPDUsTx; */
/* uint32_t dot3adAggPortStatsMarkerResponsePDUsTx; */
};
bool lacp_get_slave_stats(const struct lacp *, const void *slave_, struct lacp_slave_stats *);
#endif /* lacp.h */

View File

@ -271,6 +271,10 @@ typedef struct _SFLExtended_vlan_tunnel {
innermost. */
} SFLExtended_vlan_tunnel;
typedef struct _SFLExtended_vni {
uint32_t vni; /* virtual network identifier */
} SFLExtended_vni;
enum SFLFlow_type_tag {
/* enterprise = 0, format = ... */
SFLFLOW_HEADER = 1, /* Packet headers are sampled */
@ -289,6 +293,10 @@ enum SFLFlow_type_tag {
SFLFLOW_EX_MPLS_FTN = 1010,
SFLFLOW_EX_MPLS_LDP_FEC = 1011,
SFLFLOW_EX_VLAN_TUNNEL = 1012, /* VLAN stack */
SFLFLOW_EX_IPV4_TUNNEL_EGRESS = 1023, /* http://sflow.org/sflow_tunnels.txt */
SFLFLOW_EX_IPV4_TUNNEL_INGRESS = 1024,
SFLFLOW_EX_VNI_EGRESS = 1029,
SFLFLOW_EX_VNI_INGRESS = 1030,
};
typedef union _SFLFlow_type {
@ -308,6 +316,7 @@ typedef union _SFLFlow_type {
SFLExtended_mpls_FTN mpls_ftn;
SFLExtended_mpls_LDP_FEC mpls_ldp_fec;
SFLExtended_vlan_tunnel vlan_tunnel;
SFLExtended_vni tunnel_vni;
} SFLFlow_type;
typedef struct _SFLFlow_sample_element {
@ -386,6 +395,9 @@ typedef struct _SFLFlow_sample_expanded {
/* Counter types */
#define SFL_UNDEF_COUNTER(c) c=-1
#define SFL_UNDEF_GAUGE(c) c=0
/* Generic interface counters - see RFC 1573, 2233 */
typedef struct _SFLIf_counters {
@ -414,6 +426,8 @@ typedef struct _SFLIf_counters {
u_int32_t ifPromiscuousMode;
} SFLIf_counters;
#define SFL_CTR_GENERIC_XDR_SIZE 88
/* Ethernet interface counters - see RFC 2358 */
typedef struct _SFLEthernet_counters {
u_int32_t dot3StatsAlignmentErrors;
@ -431,6 +445,8 @@ typedef struct _SFLEthernet_counters {
u_int32_t dot3StatsSymbolErrors;
} SFLEthernet_counters;
#define SFL_CTR_ETHERNET_XDR_SIZE 52
/* Token ring counters - see RFC 1748 */
typedef struct _SFLTokenring_counters {
@ -482,6 +498,51 @@ typedef struct _SFLVlan_counters {
u_int32_t discards;
} SFLVlan_counters;
/* OpenFlow port */
typedef struct {
u_int64_t datapath_id;
u_int32_t port_no;
} SFLOpenFlowPort;
#define SFL_CTR_OPENFLOWPORT_XDR_SIZE 12
/* port name */
typedef struct {
SFLString portName;
} SFLPortName;
#define SFL_MAX_PORTNAME_LEN 255
/* LAG Port Statistics - see http://sflow.org/sflow_lag.txt */
/* opaque = counter_data; enterprise = 0; format = 7 */
typedef union _SFLLACP_portState {
uint32_t all;
struct {
uint8_t actorAdmin;
uint8_t actorOper;
uint8_t partnerAdmin;
uint8_t partnerOper;
} v;
} SFLLACP_portState;
typedef struct _SFLLACP_counters {
uint8_t actorSystemID[8]; /* 6 bytes + 2 pad */
uint8_t partnerSystemID[8]; /* 6 bytes + 2 pad */
uint32_t attachedAggID;
SFLLACP_portState portState;
uint32_t LACPDUsRx;
uint32_t markerPDUsRx;
uint32_t markerResponsePDUsRx;
uint32_t unknownRx;
uint32_t illegalRx;
uint32_t LACPDUsTx;
uint32_t markerPDUsTx;
uint32_t markerResponsePDUsTx;
} SFLLACP_counters;
#define SFL_CTR_LACP_XDR_SIZE 56
/* Counters data */
enum SFLCounters_type_tag {
@ -490,7 +551,10 @@ enum SFLCounters_type_tag {
SFLCOUNTERS_ETHERNET = 2,
SFLCOUNTERS_TOKENRING = 3,
SFLCOUNTERS_VG = 4,
SFLCOUNTERS_VLAN = 5
SFLCOUNTERS_VLAN = 5,
SFLCOUNTERS_LACP = 7,
SFLCOUNTERS_OPENFLOWPORT = 1004,
SFLCOUNTERS_PORTNAME = 1005
};
typedef union _SFLCounters_type {
@ -499,6 +563,9 @@ typedef union _SFLCounters_type {
SFLTokenring_counters tokenring;
SFLVg_counters vg;
SFLVlan_counters vlan;
SFLLACP_counters lacp;
SFLOpenFlowPort ofPort;
SFLPortName portName;
} SFLCounters_type;
typedef struct _SFLCounters_sample_element {

View File

@ -363,6 +363,21 @@ SFLPoller *sfl_agent_getPoller(SFLAgent *agent, SFLDataSource_instance *pdsi)
return NULL;
}
/*_________________-----------------------------------__________________
_________________ sfl_agent_getPollerByBridgePort __________________
-----------------___________________________________------------------
*/
SFLPoller *sfl_agent_getPollerByBridgePort(SFLAgent *agent, uint32_t port_no)
{
/* find it and return it */
SFLPoller *pl = agent->pollers;
for(; pl != NULL; pl = pl->nxt)
if(pl->bridgePort == port_no) return pl;
/* not found */
return NULL;
}
/*_________________---------------------------__________________
_________________ sfl_agent_getReceiver __________________
-----------------___________________________------------------

View File

@ -281,6 +281,7 @@ void sfl_agent_set_agentSubId(SFLAgent *agent, u_int32_t subId);
to get counters if it is not the same as the global ifIndex */
void sfl_poller_set_bridgePort(SFLPoller *poller, u_int32_t port_no);
u_int32_t sfl_poller_get_bridgePort(SFLPoller *poller);
SFLPoller *sfl_agent_getPollerByBridgePort(SFLAgent *agent, u_int32_t port_no);
/* call this to indicate a discontinuity with a counter like samplePool so that the
sflow collector will ignore the next delta */

View File

@ -464,6 +464,14 @@ static int computeFlowSampleSize(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs
case SFLFLOW_EX_MPLS_FTN: elemSiz = mplsFtnEncodingLength(&elem->flowType.mpls_ftn); break;
case SFLFLOW_EX_MPLS_LDP_FEC: elemSiz = mplsLdpFecEncodingLength(&elem->flowType.mpls_ldp_fec); break;
case SFLFLOW_EX_VLAN_TUNNEL: elemSiz = vlanTunnelEncodingLength(&elem->flowType.vlan_tunnel); break;
case SFLFLOW_EX_IPV4_TUNNEL_EGRESS:
case SFLFLOW_EX_IPV4_TUNNEL_INGRESS:
elemSiz = sizeof(SFLSampled_ipv4);
break;
case SFLFLOW_EX_VNI_EGRESS:
case SFLFLOW_EX_VNI_INGRESS:
elemSiz = sizeof(SFLExtended_vni);
break;
default:
sflError(receiver, "unexpected packet_data_tag");
return -1;
@ -560,6 +568,8 @@ int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs
putNet32(receiver, elem->flowType.ethernet.eth_type);
break;
case SFLFLOW_IPV4:
case SFLFLOW_EX_IPV4_TUNNEL_EGRESS:
case SFLFLOW_EX_IPV4_TUNNEL_INGRESS:
putNet32(receiver, elem->flowType.ipv4.length);
putNet32(receiver, elem->flowType.ipv4.protocol);
put32(receiver, elem->flowType.ipv4.src_ip.addr);
@ -591,6 +601,11 @@ int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs
case SFLFLOW_EX_MPLS_FTN: putMplsFtn(receiver, &elem->flowType.mpls_ftn); break;
case SFLFLOW_EX_MPLS_LDP_FEC: putMplsLdpFec(receiver, &elem->flowType.mpls_ldp_fec); break;
case SFLFLOW_EX_VLAN_TUNNEL: putVlanTunnel(receiver, &elem->flowType.vlan_tunnel); break;
case SFLFLOW_EX_VNI_EGRESS:
case SFLFLOW_EX_VNI_INGRESS:
putNet32(receiver, elem->flowType.tunnel_vni.vni);
break;
default:
sflError(receiver, "unexpected packet_data_tag");
return -1;
@ -629,11 +644,14 @@ static int computeCountersSampleSize(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_
cs->num_elements++;
siz += 8; /* tag, length */
switch(elem->tag) {
case SFLCOUNTERS_GENERIC: elemSiz = sizeof(elem->counterBlock.generic); break;
case SFLCOUNTERS_ETHERNET: elemSiz = sizeof(elem->counterBlock.ethernet); break;
case SFLCOUNTERS_GENERIC: elemSiz = SFL_CTR_GENERIC_XDR_SIZE; break;
case SFLCOUNTERS_ETHERNET: elemSiz = SFL_CTR_ETHERNET_XDR_SIZE; break;
case SFLCOUNTERS_TOKENRING: elemSiz = sizeof(elem->counterBlock.tokenring); break;
case SFLCOUNTERS_VG: elemSiz = sizeof(elem->counterBlock.vg); break;
case SFLCOUNTERS_VLAN: elemSiz = sizeof(elem->counterBlock.vlan); break;
case SFLCOUNTERS_LACP: elemSiz = SFL_CTR_LACP_XDR_SIZE; break;
case SFLCOUNTERS_OPENFLOWPORT: elemSiz = SFL_CTR_OPENFLOWPORT_XDR_SIZE; break;
case SFLCOUNTERS_PORTNAME: elemSiz = stringEncodingLength(&elem->counterBlock.portName.portName); break;
default:
sflError(receiver, "unexpected counters_tag");
return -1;
@ -735,6 +753,27 @@ int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_
putNet32(receiver, elem->counterBlock.vlan.broadcastPkts);
putNet32(receiver, elem->counterBlock.vlan.discards);
break;
case SFLCOUNTERS_LACP:
putMACAddress(receiver, elem->counterBlock.lacp.actorSystemID);
putMACAddress(receiver, elem->counterBlock.lacp.partnerSystemID);
putNet32(receiver, elem->counterBlock.lacp.attachedAggID);
put32(receiver, elem->counterBlock.lacp.portState.all);
putNet32(receiver, elem->counterBlock.lacp.LACPDUsRx);
putNet32(receiver, elem->counterBlock.lacp.markerPDUsRx);
putNet32(receiver, elem->counterBlock.lacp.markerResponsePDUsRx);
putNet32(receiver, elem->counterBlock.lacp.unknownRx);
putNet32(receiver, elem->counterBlock.lacp.illegalRx);
putNet32(receiver, elem->counterBlock.lacp.LACPDUsTx);
putNet32(receiver, elem->counterBlock.lacp.markerPDUsTx);
putNet32(receiver, elem->counterBlock.lacp.markerResponsePDUsTx);
break;
case SFLCOUNTERS_OPENFLOWPORT:
putNet64(receiver, elem->counterBlock.ofPort.datapath_id);
putNet32(receiver, elem->counterBlock.ofPort.port_no);
break;
case SFLCOUNTERS_PORTNAME:
putString(receiver, &elem->counterBlock.portName.portName);
break;
default:
sflError(receiver, "unexpected counters_tag");
return -1;

View File

@ -40,6 +40,7 @@
#include "vlog.h"
#include "lib/odp-util.h"
#include "ofproto-provider.h"
#include "lacp.h"
VLOG_DEFINE_THIS_MODULE(sflow);
@ -166,12 +167,14 @@ sflow_agent_get_counters(void *ds_, SFLPoller *poller,
OVS_REQUIRES(mutex)
{
struct dpif_sflow *ds = ds_;
SFLCounters_sample_element elem;
SFLCounters_sample_element elem, lacp_elem, of_elem, name_elem;
enum netdev_features current;
struct dpif_sflow_port *dsp;
SFLIf_counters *counters;
struct netdev_stats stats;
enum netdev_flags flags;
struct lacp_slave_stats lacp_stats;
const char *ifName;
dsp = dpif_sflow_find_port(ds, u32_to_odp(poller->bridgePort));
if (!dsp) {
@ -223,6 +226,59 @@ sflow_agent_get_counters(void *ds_, SFLPoller *poller,
counters->ifPromiscuousMode = 0;
SFLADD_ELEMENT(cs, &elem);
/* Include LACP counters and identifiers if this port is part of a LAG. */
if (ofproto_port_get_lacp_stats(dsp->ofport, &lacp_stats) == 0) {
memset(&lacp_elem, 0, sizeof lacp_elem);
lacp_elem.tag = SFLCOUNTERS_LACP;
memcpy(&lacp_elem.counterBlock.lacp.actorSystemID,
lacp_stats.dot3adAggPortActorSystemID,
ETH_ADDR_LEN);
memcpy(&lacp_elem.counterBlock.lacp.partnerSystemID,
lacp_stats.dot3adAggPortPartnerOperSystemID,
ETH_ADDR_LEN);
lacp_elem.counterBlock.lacp.attachedAggID =
lacp_stats.dot3adAggPortAttachedAggID;
lacp_elem.counterBlock.lacp.portState.v.actorAdmin =
lacp_stats.dot3adAggPortActorAdminState;
lacp_elem.counterBlock.lacp.portState.v.actorOper =
lacp_stats.dot3adAggPortActorOperState;
lacp_elem.counterBlock.lacp.portState.v.partnerAdmin =
lacp_stats.dot3adAggPortPartnerAdminState;
lacp_elem.counterBlock.lacp.portState.v.partnerOper =
lacp_stats.dot3adAggPortPartnerOperState;
lacp_elem.counterBlock.lacp.LACPDUsRx =
lacp_stats.dot3adAggPortStatsLACPDUsRx;
SFL_UNDEF_COUNTER(lacp_elem.counterBlock.lacp.markerPDUsRx);
SFL_UNDEF_COUNTER(lacp_elem.counterBlock.lacp.markerResponsePDUsRx);
SFL_UNDEF_COUNTER(lacp_elem.counterBlock.lacp.unknownRx);
lacp_elem.counterBlock.lacp.illegalRx =
lacp_stats.dot3adAggPortStatsIllegalRx;
lacp_elem.counterBlock.lacp.LACPDUsTx =
lacp_stats.dot3adAggPortStatsLACPDUsTx;
SFL_UNDEF_COUNTER(lacp_elem.counterBlock.lacp.markerPDUsTx);
SFL_UNDEF_COUNTER(lacp_elem.counterBlock.lacp.markerResponsePDUsTx);
SFLADD_ELEMENT(cs, &lacp_elem);
}
/* Include Port name. */
if ((ifName = netdev_get_name(dsp->ofport->netdev)) != NULL) {
memset(&name_elem, 0, sizeof name_elem);
name_elem.tag = SFLCOUNTERS_PORTNAME;
name_elem.counterBlock.portName.portName.str = (char *)ifName;
name_elem.counterBlock.portName.portName.len = strlen(ifName);
SFLADD_ELEMENT(cs, &name_elem);
}
/* Include OpenFlow DPID and openflow port number. */
memset(&of_elem, 0, sizeof of_elem);
of_elem.tag = SFLCOUNTERS_OPENFLOWPORT;
of_elem.counterBlock.ofPort.datapath_id =
ofproto_get_datapath_id(dsp->ofport->ofproto);
of_elem.counterBlock.ofPort.port_no =
(OVS_FORCE uint32_t)dsp->ofport->ofp_port;
SFLADD_ELEMENT(cs, &of_elem);
sfl_poller_writeCountersSample(poller, cs);
}

View File

@ -3310,6 +3310,18 @@ port_get_stats(const struct ofport *ofport_, struct netdev_stats *stats)
return error;
}
static int
port_get_lacp_stats(const struct ofport *ofport_, struct lacp_slave_stats *stats)
{
struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
if (ofport->bundle && ofport->bundle->lacp) {
if (lacp_get_slave_stats(ofport->bundle->lacp, ofport, stats)) {
return 0;
}
}
return -1;
}
struct port_dump_state {
uint32_t bucket;
uint32_t offset;
@ -5378,6 +5390,7 @@ const struct ofproto_class ofproto_dpif_class = {
port_poll,
port_poll_wait,
port_is_lacp_current,
port_get_lacp_stats,
NULL, /* rule_choose_table */
rule_alloc,
rule_construct,

View File

@ -1036,6 +1036,14 @@ struct ofproto_class {
* not support LACP. */
int (*port_is_lacp_current)(const struct ofport *port);
/* Get LACP port stats. Returns -1 if LACP is not enabled on 'port'.
*
* This function may be a null pointer if the ofproto implementation does
* not support LACP. */
int (*port_get_lacp_stats)(const struct ofport *port,
struct lacp_slave_stats *stats);
/* ## ----------------------- ## */
/* ## OpenFlow Rule Functions ## */
/* ## ----------------------- ## */

View File

@ -1147,6 +1147,21 @@ ofproto_port_is_lacp_current(struct ofproto *ofproto, ofp_port_t ofp_port)
? ofproto->ofproto_class->port_is_lacp_current(ofport)
: -1);
}
int
ofproto_port_get_lacp_stats(const struct ofport *port, struct lacp_slave_stats *stats)
{
struct ofproto *ofproto = port->ofproto;
int error;
if (ofproto->ofproto_class->port_get_lacp_stats) {
error = ofproto->ofproto_class->port_get_lacp_stats(port, stats);
} else {
error = EOPNOTSUPP;
}
return error;
}
/* Bundles. */

View File

@ -31,6 +31,7 @@
#include "smap.h"
#include "sset.h"
#include "stp.h"
#include "lacp.h"
#ifdef __cplusplus
extern "C" {
@ -330,6 +331,7 @@ bool ofproto_port_bfd_status_changed(struct ofproto *, ofp_port_t ofp_port);
int ofproto_port_get_bfd_status(struct ofproto *, ofp_port_t ofp_port,
struct smap *);
int ofproto_port_is_lacp_current(struct ofproto *, ofp_port_t ofp_port);
int ofproto_port_get_lacp_stats(const struct ofport *, struct lacp_slave_stats *);
int ofproto_port_set_stp(struct ofproto *, ofp_port_t ofp_port,
const struct ofproto_port_stp_settings *);
int ofproto_port_get_stp_status(struct ofproto *, ofp_port_t ofp_port,

View File

@ -4370,7 +4370,7 @@ HEADER
hdr=50-54-00-00-00-05-50-54-00-00-00-07-86-DD-67-00-00-00-00-00-0A-80-FE-80-00-00-00-00-00-00-00-00-00-00-00-00-00-01-FE-80-00-00-00-00-00-00-00-00-00-00-00-00-00-02-00-00-00-00-00-00
])
AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'IFCOUNTERS|ERROR' | head -6 | sed 's/ /\
AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'IFCOUNTERS|ERROR|PORTNAME|OPENFLOWPORT' | head -18 | sed 's/ /\
/g']], [0], [dnl
IFCOUNTERS
dgramSeqNo=2
@ -4510,12 +4510,100 @@ IFCOUNTERS
out_discards=0
out_errors=0
promiscuous=0
OPENFLOWPORT
datapath_id=18364758544493064720
port_no=1
OPENFLOWPORT
datapath_id=18364758544493064720
port_no=1
OPENFLOWPORT
datapath_id=18364758544493064720
port_no=2
OPENFLOWPORT
datapath_id=18364758544493064720
port_no=2
OPENFLOWPORT
datapath_id=18364758544493064720
port_no=65534
OPENFLOWPORT
datapath_id=18364758544493064720
port_no=65534
PORTNAME
portName=br0
PORTNAME
portName=br0
PORTNAME
portName=p1
PORTNAME
portName=p1
PORTNAME
portName=p2
PORTNAME
portName=p2
])
AT_CLEANUP])
CHECK_SFLOW_SAMPLING_PACKET([127.0.0.1], [IPv4])
CHECK_SFLOW_SAMPLING_PACKET([[[::1]]], [IPv6])
dnl Test sFlow LAG structures
AT_SETUP([ofproto-dpif - sFlow LACP structures])
OVS_VSWITCHD_START([dnl
add-bond br0 bond p1 p2 -- \
set Port bond lacp=active bond-mode=active-backup \
other_config:lacp-time="fast" \
other_config:lacp-system-id=11:22:33:44:55:66 \
other_config:lacp-system-priority=54321 -- \
set Interface p1 type=dummy \
other_config:lacp-port-id=11 \
other_config:lacp-port-priority=111 \
other_config:lacp-aggregation-key=3333 -- \
set Interface p2 type=dummy \
other_config:lacp-port-id=22 \
other_config:lacp-port-priority=222 \
other_config:lacp-aggregation-key=3333 ])
ON_EXIT([kill `cat test-sflow.pid`])
AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([sflow.log])
SFLOW_PORT=`parse_listening_port < test-sflow.log`
ovs-appctl time/stop
ovs-vsctl \
set Interface p1 options:ifindex=1003 -- \
set Bridge br0 sflow=@sf -- \
--id=@sf create sflow targets=\"127.0.0.1:$SFLOW_PORT\" \
header=128 sampling=1 polling=1
dnl sleep long enough to get the sFlow datagram flushed out (may be delayed for up to 1 second)
for i in `seq 1 30`; do
ovs-appctl time/warp 100
done
OVS_VSWITCHD_STOP
ovs-appctl -t test-sflow exit
AT_CHECK([[sort sflow.log | $EGREP 'LACPCOUNTERS|ERROR' | head -n 1 | sed 's/ /\
/g']], [0], [dnl
LACPCOUNTERS
sysID=11:22:33:44:55:66
partnerID=00:00:00:00:00:00
aggID=3333
actorAdmin=0x7
actorOper=0xbf
partnerAdmin=0x0
partnerOper=0x2
LACPUDsRx=0
markerPDUsRx=4294967295
markerRespPDUsRx=4294967295
unknownRx=4294967295
illegalRx=0
LACPUDsTx=1
markerPDUsTx=4294967295
markerRespPDUsTx=4294967295
])
AT_CLEANUP
# CHECK_NETFLOW_EXPIRATION(LOOPBACK_ADDR, IP_VERSION_TYPE)
#
# Test that basic NetFlow reports flow statistics correctly:

View File

@ -54,8 +54,18 @@ static unixctl_cb_func test_sflow_exit;
/* Structure element tag numbers. */
#define SFLOW_TAG_CTR_IFCOUNTERS 1
#define SFLOW_TAG_CTR_LACPCOUNTERS 7
#define SFLOW_TAG_CTR_OPENFLOWPORT 1004
#define SFLOW_TAG_CTR_PORTNAME 1005
#define SFLOW_TAG_PKT_HEADER 1
#define SFLOW_TAG_PKT_SWITCH 1001
#define SFLOW_TAG_PKT_TUNNEL4_OUT 1023
#define SFLOW_TAG_PKT_TUNNEL4_IN 1024
#define SFLOW_TAG_PKT_TUNNEL_VNI_OUT 1029
#define SFLOW_TAG_PKT_TUNNEL_VNI_IN 1030
/* string sizes */
#define SFL_MAX_PORTNAME_LEN 255
struct sflow_addr {
enum {
@ -99,7 +109,14 @@ struct sflow_xdr {
struct {
uint32_t HEADER;
uint32_t SWITCH;
uint32_t TUNNEL4_OUT;
uint32_t TUNNEL4_IN;
uint32_t TUNNEL_VNI_OUT;
uint32_t TUNNEL_VNI_IN;
uint32_t IFCOUNTERS;
uint32_t LACPCOUNTERS;
uint32_t OPENFLOWPORT;
uint32_t PORTNAME;
} offset;
/* Flow sample fields. */
@ -221,6 +238,63 @@ process_counter_sample(struct sflow_xdr *x)
printf(" promiscuous=%"PRIu32, sflowxdr_next(x));
printf("\n");
}
if (x->offset.LACPCOUNTERS) {
uint8_t *mac;
union {
ovs_be32 all;
struct {
uint8_t actorAdmin;
uint8_t actorOper;
uint8_t partnerAdmin;
uint8_t partnerOper;
} v;
} state;
sflowxdr_setc(x, x->offset.LACPCOUNTERS);
printf("LACPCOUNTERS");
mac = (uint8_t *)sflowxdr_str(x);
printf(" sysID="ETH_ADDR_FMT, ETH_ADDR_ARGS(mac));
sflowxdr_skip(x, 2);
mac = (uint8_t *)sflowxdr_str(x);
printf(" partnerID="ETH_ADDR_FMT, ETH_ADDR_ARGS(mac));
sflowxdr_skip(x, 2);
printf(" aggID=%"PRIu32, sflowxdr_next(x));
state.all = sflowxdr_next_n(x);
printf(" actorAdmin=0x%"PRIx32, state.v.actorAdmin);
printf(" actorOper=0x%"PRIx32, state.v.actorOper);
printf(" partnerAdmin=0x%"PRIx32, state.v.partnerAdmin);
printf(" partnerOper=0x%"PRIx32, state.v.partnerOper);
printf(" LACPUDsRx=%"PRIu32, sflowxdr_next(x));
printf(" markerPDUsRx=%"PRIu32, sflowxdr_next(x));
printf(" markerRespPDUsRx=%"PRIu32, sflowxdr_next(x));
printf(" unknownRx=%"PRIu32, sflowxdr_next(x));
printf(" illegalRx=%"PRIu32, sflowxdr_next(x));
printf(" LACPUDsTx=%"PRIu32, sflowxdr_next(x));
printf(" markerPDUsTx=%"PRIu32, sflowxdr_next(x));
printf(" markerRespPDUsTx=%"PRIu32, sflowxdr_next(x));
printf("\n");
}
if (x->offset.OPENFLOWPORT) {
sflowxdr_setc(x, x->offset.OPENFLOWPORT);
printf("OPENFLOWPORT");
printf(" datapath_id=%"PRIu64, sflowxdr_next_int64(x));
printf(" port_no=%"PRIu32, sflowxdr_next(x));
printf("\n");
}
if (x->offset.PORTNAME) {
uint32_t pnLen;
const char *pnBytes;
char portName[SFL_MAX_PORTNAME_LEN + 1];
sflowxdr_setc(x, x->offset.PORTNAME);
printf("PORTNAME");
pnLen = sflowxdr_next(x);
SFLOWXDR_assert(x, (pnLen <= SFL_MAX_PORTNAME_LEN));
pnBytes = sflowxdr_str(x);
memcpy(portName, pnBytes, pnLen);
portName[pnLen] = '\0';
printf(" portName=%s", portName);
printf("\n");
}
}
static char
@ -251,6 +325,25 @@ print_hex(const char *a, int len, char *buf, int bufLen)
return b;
}
static void
print_struct_ipv4(struct sflow_xdr *x, const char *prefix)
{
ovs_be32 src, dst;
printf(" %s_length=%"PRIu32, prefix, sflowxdr_next(x));
printf(" %s_protocol=%"PRIu32, prefix, sflowxdr_next(x));
src = sflowxdr_next_n(x);
dst = sflowxdr_next_n(x);
printf(" %s_src="IP_FMT, prefix, IP_ARGS(src));
printf(" %s_dst="IP_FMT, prefix, IP_ARGS(dst));
printf(" %s_src_port=%"PRIu32, prefix, sflowxdr_next(x));
printf(" %s_dst_port=%"PRIu32, prefix, sflowxdr_next(x));
printf(" %s_tcp_flags=%"PRIu32, prefix, sflowxdr_next(x));
printf(" %s_tos=%"PRIu32, prefix, sflowxdr_next(x));
}
#define SFLOW_HEX_SCRATCH 1024
static void
@ -266,6 +359,26 @@ process_flow_sample(struct sflow_xdr *x)
x->agentIPStr, x->dsClass, x->dsIndex);
printf(" fsSeqNo=%"PRIu32, x->fsSeqNo);
if (x->offset.TUNNEL4_IN) {
sflowxdr_setc(x, x->offset.TUNNEL4_IN);
print_struct_ipv4(x, "tunnel4_in");
}
if (x->offset.TUNNEL4_OUT) {
sflowxdr_setc(x, x->offset.TUNNEL4_OUT);
print_struct_ipv4(x, "tunnel4_out");
}
if (x->offset.TUNNEL_VNI_IN) {
sflowxdr_setc(x, x->offset.TUNNEL_VNI_IN);
printf( " tunnel_in_vni=%"PRIu32, sflowxdr_next(x));
}
if (x->offset.TUNNEL_VNI_OUT) {
sflowxdr_setc(x, x->offset.TUNNEL_VNI_OUT);
printf( " tunnel_out_vni=%"PRIu32, sflowxdr_next(x));
}
if (x->offset.SWITCH) {
sflowxdr_setc(x, x->offset.SWITCH);
printf(" in_vlan=%"PRIu32, sflowxdr_next(x));
@ -372,6 +485,15 @@ process_datagram(struct sflow_xdr *x)
case SFLOW_TAG_CTR_IFCOUNTERS:
sflowxdr_mark_unique(x, &x->offset.IFCOUNTERS);
break;
case SFLOW_TAG_CTR_LACPCOUNTERS:
sflowxdr_mark_unique(x, &x->offset.LACPCOUNTERS);
break;
case SFLOW_TAG_CTR_PORTNAME:
sflowxdr_mark_unique(x, &x->offset.PORTNAME);
break;
case SFLOW_TAG_CTR_OPENFLOWPORT:
sflowxdr_mark_unique(x, &x->offset.OPENFLOWPORT);
break;
/* Add others here... */
}
@ -440,6 +562,22 @@ process_datagram(struct sflow_xdr *x)
sflowxdr_mark_unique(x, &x->offset.SWITCH);
break;
case SFLOW_TAG_PKT_TUNNEL4_OUT:
sflowxdr_mark_unique(x, &x->offset.TUNNEL4_OUT);
break;
case SFLOW_TAG_PKT_TUNNEL4_IN:
sflowxdr_mark_unique(x, &x->offset.TUNNEL4_IN);
break;
case SFLOW_TAG_PKT_TUNNEL_VNI_OUT:
sflowxdr_mark_unique(x, &x->offset.TUNNEL_VNI_OUT);
break;
case SFLOW_TAG_PKT_TUNNEL_VNI_IN:
sflowxdr_mark_unique(x, &x->offset.TUNNEL_VNI_IN);
break;
/* Add others here... */
}