Protocol stats: Add OpenFlow protocol statistical information
collector Fix BUG#49: Add OpenFlow protocol statistical information collector and user interface. This feature use PRIVATE_VENDOR_ID to communicate betwewn control plane process and user interface. PRIVATE_VENDOR_ID is defined only for private use (and based on private OUI).
This commit is contained in:
1 parent
e61c00c0bb
commit
d56d5661df
18 files changed
+911
No files matched your search
@@ -45,6 +45,8 @@ lib_libopenflow_a_SOURCES = \
|
||||
lib/ofp-print.h \
|
||||
lib/ofpbuf.c \
|
||||
lib/ofpbuf.h \
|
||||
lib/ofpstat.c \
|
||||
lib/ofpstat.h \
|
||||
lib/packets.h \
|
||||
lib/pcap.c \
|
||||
lib/pcap.h \
|
||||
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
/*-
|
||||
* Copyright (c) 2008, 2009
|
||||
* The Board of Trustees of The Leland Stanford Junior University
|
||||
*
|
||||
* We are making the OpenFlow specification and associated documentation
|
||||
* (Software) available for public use and benefit with the expectation that
|
||||
* others will use, modify and enhance the Software and contribute those
|
||||
* enhancements back to the community. However, since we would like to make the
|
||||
* Software available for broadest use, with as few restrictions as possible
|
||||
* permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this Software to deal in the Software under the copyrights without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* The name and trademarks of copyright holder(s) may NOT be used in
|
||||
* advertising or publicity pertaining to the Software or any derivatives
|
||||
* without specific, written prior permission.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "openflow/openflow.h"
|
||||
#include "ofpstat.h"
|
||||
|
||||
#define INC_IFP_STAT(ifps, tag) do {++(ifps)->tag;} while (0)
|
||||
|
||||
static void inc_protocol_message(struct ofpstat *, struct ofp_header *);
|
||||
static void inc_error_notification(struct ofpstat *, struct ofp_header *);
|
||||
static void inc_flow_manipulation(struct ofpstat *, struct ofp_header *);
|
||||
|
||||
static void
|
||||
inc_protocol_message(struct ofpstat *ifps, struct ofp_header *hdr)
|
||||
{
|
||||
switch (hdr->type) {
|
||||
case OFPT_HELLO:
|
||||
INC_IFP_STAT(ifps, ofps_hello);
|
||||
break;
|
||||
case OFPT_ERROR:
|
||||
INC_IFP_STAT(ifps, ofps_error);
|
||||
break;
|
||||
case OFPT_ECHO_REQUEST:
|
||||
INC_IFP_STAT(ifps, ofps_echo_request);
|
||||
break;
|
||||
case OFPT_ECHO_REPLY:
|
||||
INC_IFP_STAT(ifps, ofps_echo_reply);
|
||||
break;
|
||||
case OFPT_VENDOR:
|
||||
INC_IFP_STAT(ifps, ofps_vendor);
|
||||
break;
|
||||
case OFPT_FEATURES_REQUEST:
|
||||
INC_IFP_STAT(ifps, ofps_feats_request);
|
||||
break;
|
||||
case OFPT_FEATURES_REPLY:
|
||||
INC_IFP_STAT(ifps, ofps_feats_reply);
|
||||
break;
|
||||
case OFPT_GET_CONFIG_REQUEST:
|
||||
INC_IFP_STAT(ifps, ofps_get_config_request);
|
||||
break;
|
||||
case OFPT_GET_CONFIG_REPLY:
|
||||
INC_IFP_STAT(ifps, ofps_get_config_reply);
|
||||
break;
|
||||
case OFPT_SET_CONFIG:
|
||||
INC_IFP_STAT(ifps, ofps_set_config);
|
||||
break;
|
||||
case OFPT_PACKET_IN:
|
||||
INC_IFP_STAT(ifps, ofps_packet_in);
|
||||
break;
|
||||
case OFPT_FLOW_EXPIRED:
|
||||
INC_IFP_STAT(ifps, ofps_flow_expired);
|
||||
break;
|
||||
case OFPT_PORT_STATUS:
|
||||
INC_IFP_STAT(ifps, ofps_port_status);
|
||||
break;
|
||||
case OFPT_PACKET_OUT:
|
||||
INC_IFP_STAT(ifps, ofps_packet_out);
|
||||
break;
|
||||
case OFPT_FLOW_MOD:
|
||||
INC_IFP_STAT(ifps, ofps_flow_mod);
|
||||
break;
|
||||
case OFPT_PORT_MOD:
|
||||
INC_IFP_STAT(ifps, ofps_port_mod);
|
||||
break;
|
||||
case OFPT_STATS_REQUEST:
|
||||
INC_IFP_STAT(ifps, ofps_stats_request);
|
||||
break;
|
||||
case OFPT_STATS_REPLY:
|
||||
INC_IFP_STAT(ifps, ofps_stats_reply);
|
||||
break;
|
||||
default:
|
||||
INC_IFP_STAT(ifps, ofps_unknown);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
inc_error_notification(struct ofpstat *ifps, struct ofp_header *hdr)
|
||||
{
|
||||
struct ofp_error_msg *errmsg = (struct ofp_error_msg *)hdr;
|
||||
uint16_t errtype = ntohs(errmsg->type);
|
||||
uint16_t errcode = ntohs(errmsg->code);
|
||||
|
||||
switch (errtype) {
|
||||
case OFPET_HELLO_FAILED:
|
||||
INC_IFP_STAT(ifps, ofps_error_type.hello_fail);
|
||||
switch (errcode) {
|
||||
case OFPHFC_INCOMPATIBLE:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.hf_incompat);
|
||||
break;
|
||||
default:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.unknown);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OFPET_BAD_REQUEST:
|
||||
INC_IFP_STAT(ifps, ofps_error_type.bad_request);
|
||||
switch (errcode) {
|
||||
case OFPBRC_BAD_VERSION:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.br_bad_version);
|
||||
break;
|
||||
case OFPBRC_BAD_TYPE:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.br_bad_type);
|
||||
break;
|
||||
case OFPBRC_BAD_STAT:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.br_bad_stat);
|
||||
break;
|
||||
case OFPBRC_BAD_VENDOR:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.br_bad_vendor);
|
||||
break;
|
||||
default:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.unknown);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OFPET_BAD_ACTION:
|
||||
INC_IFP_STAT(ifps, ofps_error_type.bad_action);
|
||||
switch (errcode) {
|
||||
case OFPBAC_BAD_TYPE:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_type);
|
||||
break;
|
||||
case OFPBAC_BAD_LEN:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_len);
|
||||
break;
|
||||
case OFPBAC_BAD_VENDOR:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_vendor);
|
||||
break;
|
||||
case OFPBAC_BAD_VENDOR_TYPE:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_vendor_type);
|
||||
break;
|
||||
case OFPBAC_BAD_OUT_PORT:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_out_port);
|
||||
break;
|
||||
case OFPBAC_BAD_ARGUMENT:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_argument);
|
||||
break;
|
||||
default:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.unknown);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OFPET_FLOW_MOD_FAILED:
|
||||
INC_IFP_STAT(ifps, ofps_error_type.flow_mod_fail);
|
||||
switch (errcode) {
|
||||
case OFPFMFC_ALL_TABLES_FULL:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.fmf_all_tables_full);
|
||||
break;
|
||||
default:
|
||||
INC_IFP_STAT(ifps, ofps_error_code.unknown);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
INC_IFP_STAT(ifps, ofps_error_type.unknown);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
inc_flow_manipulation(struct ofpstat *ifps, struct ofp_header *hdr)
|
||||
{
|
||||
struct ofp_flow_mod *flowmodmsg = (struct ofp_flow_mod *)hdr;
|
||||
uint16_t flowmodops = ntohs(flowmodmsg->command);
|
||||
|
||||
switch (flowmodops) {
|
||||
case OFPFC_ADD:
|
||||
INC_IFP_STAT(ifps, ofps_flow_mod_ops.add);
|
||||
break;
|
||||
case OFPFC_MODIFY:
|
||||
INC_IFP_STAT(ifps, ofps_flow_mod_ops.modify);
|
||||
break;
|
||||
case OFPFC_MODIFY_STRICT:
|
||||
INC_IFP_STAT(ifps, ofps_flow_mod_ops.modify_strict);
|
||||
break;
|
||||
case OFPFC_DELETE:
|
||||
INC_IFP_STAT(ifps, ofps_flow_mod_ops.delete);
|
||||
break;
|
||||
case OFPFC_DELETE_STRICT:
|
||||
INC_IFP_STAT(ifps, ofps_flow_mod_ops.delete_strict);
|
||||
break;
|
||||
default:
|
||||
INC_IFP_STAT(ifps, ofps_flow_mod_ops.unknown);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ofpstat_inc_protocol_stat(struct ofpstat *ifps, struct ofp_header *hdr)
|
||||
{
|
||||
++ifps->ofps_total;
|
||||
inc_protocol_message(ifps, hdr);
|
||||
|
||||
switch (hdr->type) {
|
||||
case OFPT_ERROR:
|
||||
inc_error_notification(ifps, hdr);
|
||||
break;
|
||||
case OFPT_FLOW_MOD:
|
||||
inc_flow_manipulation(ifps, hdr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*-
|
||||
* Copyright (c) 2008, 2009
|
||||
* The Board of Trustees of The Leland Stanford Junior University
|
||||
*
|
||||
* We are making the OpenFlow specification and associated documentation
|
||||
* (Software) available for public use and benefit with the expectation that
|
||||
* others will use, modify and enhance the Software and contribute those
|
||||
* enhancements back to the community. However, since we would like to make the
|
||||
* Software available for broadest use, with as few restrictions as possible
|
||||
* permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this Software to deal in the Software under the copyrights without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* The name and trademarks of copyright holder(s) may NOT be used in
|
||||
* advertising or publicity pertaining to the Software or any derivatives
|
||||
* without specific, written prior permission.
|
||||
*/
|
||||
|
||||
#ifndef OFPSTAT_H_
|
||||
#define OFPSTAT_H_
|
||||
|
||||
struct ofpstat {
|
||||
uint64_t ofps_total;
|
||||
uint64_t ofps_unknown;
|
||||
|
||||
uint64_t ofps_hello;
|
||||
uint64_t ofps_error;
|
||||
struct {
|
||||
uint64_t hello_fail;
|
||||
uint64_t bad_request;
|
||||
uint64_t bad_action;
|
||||
uint64_t flow_mod_fail;
|
||||
uint64_t unknown;
|
||||
} ofps_error_type;
|
||||
struct {
|
||||
uint64_t hf_incompat;
|
||||
uint64_t br_bad_version;
|
||||
uint64_t br_bad_type;
|
||||
uint64_t br_bad_stat;
|
||||
uint64_t br_bad_vendor;
|
||||
uint64_t ba_bad_type;
|
||||
uint64_t ba_bad_len;
|
||||
uint64_t ba_bad_vendor;
|
||||
uint64_t ba_bad_vendor_type;
|
||||
uint64_t ba_bad_out_port;
|
||||
uint64_t ba_bad_argument;
|
||||
uint64_t fmf_all_tables_full;
|
||||
uint64_t unknown;
|
||||
} ofps_error_code;
|
||||
uint64_t ofps_echo_request;
|
||||
uint64_t ofps_echo_reply;
|
||||
uint64_t ofps_vendor;
|
||||
uint64_t ofps_feats_request;
|
||||
uint64_t ofps_feats_reply;
|
||||
uint64_t ofps_get_config_request;
|
||||
uint64_t ofps_get_config_reply;
|
||||
uint64_t ofps_set_config;
|
||||
uint64_t ofps_packet_in;
|
||||
uint64_t ofps_flow_expired;
|
||||
uint64_t ofps_port_status;
|
||||
uint64_t ofps_packet_out;
|
||||
uint64_t ofps_flow_mod;
|
||||
struct {
|
||||
uint64_t add;
|
||||
uint64_t modify;
|
||||
uint64_t modify_strict;
|
||||
uint64_t delete;
|
||||
uint64_t delete_strict;
|
||||
uint64_t unknown;
|
||||
} ofps_flow_mod_ops;
|
||||
uint64_t ofps_port_mod;
|
||||
uint64_t ofps_stats_request;
|
||||
uint64_t ofps_stats_reply;
|
||||
};
|
||||
|
||||
void ofpstat_inc_protocol_stat(struct ofpstat *, struct ofp_header *);
|
||||
|
||||
#endif
|
||||
+37
@@ -45,6 +45,7 @@
|
||||
#include "timeval.h"
|
||||
#include "util.h"
|
||||
#include "vconn.h"
|
||||
#include "vconn-provider.h"
|
||||
|
||||
#define THIS_MODULE VLM_rconn
|
||||
#include "vlog.h"
|
||||
@@ -476,6 +477,7 @@ rconn_recv(struct rconn *rc)
|
||||
struct ofpbuf *buffer;
|
||||
int error = vconn_recv(rc->vconn, &buffer);
|
||||
if (!error) {
|
||||
struct ofp_header *h = buffer->data;
|
||||
copy_to_monitor(rc, buffer);
|
||||
if (is_admitted_msg(buffer)
|
||||
|| time_now() - rc->last_connected >= 30) {
|
||||
@@ -484,6 +486,7 @@ rconn_recv(struct rconn *rc)
|
||||
}
|
||||
rc->last_received = time_now();
|
||||
rc->packets_received++;
|
||||
ofpstat_inc_protocol_stat(&rc->ofps_rcvd, h);
|
||||
if (rc->state == S_IDLE) {
|
||||
/* Check liveliness of a peer. */
|
||||
if (h->type == OFPT_ECHO_REPLY) {
|
||||
@@ -734,6 +737,39 @@ rconn_get_connection_seqno(const struct rconn *rc)
|
||||
{
|
||||
return rc->seqno;
|
||||
}
|
||||
|
||||
/* Returns protocol statistical information. */
|
||||
void
|
||||
rconn_update_protocol_stat(struct rconn *rconn,
|
||||
struct ofpstat *ofps_rcvd,
|
||||
struct ofpstat *ofps_sent)
|
||||
{
|
||||
struct vconn *vconn = rconn->vconn;
|
||||
|
||||
if (vconn != NULL) {
|
||||
rconn->ofps_rcvd.ofps_total += vconn->ofps_rcvd.ofps_total;
|
||||
vconn->ofps_rcvd.ofps_total = 0;
|
||||
rconn->ofps_rcvd.ofps_hello += vconn->ofps_rcvd.ofps_hello;
|
||||
vconn->ofps_rcvd.ofps_hello = 0;
|
||||
}
|
||||
*ofps_rcvd = rconn->ofps_rcvd;
|
||||
|
||||
if (vconn != NULL) {
|
||||
rconn->ofps_sent.ofps_total += vconn->ofps_sent.ofps_total;
|
||||
vconn->ofps_sent.ofps_total = 0;
|
||||
rconn->ofps_sent.ofps_hello += vconn->ofps_sent.ofps_hello;
|
||||
vconn->ofps_sent.ofps_hello = 0;
|
||||
rconn->ofps_sent.ofps_error += vconn->ofps_sent.ofps_error;
|
||||
vconn->ofps_sent.ofps_error = 0;
|
||||
rconn->ofps_sent.ofps_error_type.hello_fail
|
||||
+= vconn->ofps_sent.ofps_error_type.hello_fail;
|
||||
vconn->ofps_sent.ofps_error_type.hello_fail = 0;
|
||||
rconn->ofps_sent.ofps_error_code.hf_incompat
|
||||
+= vconn->ofps_sent.ofps_error_code.hf_incompat;
|
||||
vconn->ofps_sent.ofps_error_code.hf_incompat = 0;
|
||||
}
|
||||
*ofps_sent = rconn->ofps_sent;
|
||||
}
|
||||
|
||||
/* Tries to send a packet from 'rc''s send buffer. Returns 0 if successful,
|
||||
* otherwise a positive errno value. */
|
||||
@@ -742,6 +778,7 @@ try_send(struct rconn *rc)
|
||||
{
|
||||
int retval = 0;
|
||||
struct ofpbuf *next = rc->txq.head->next;
|
||||
struct ofp_header *h = rc->txq.head->data;
|
||||
int *n_queued = rc->txq.head->private;
|
||||
ofpstat_inc_protocol_stat(&rc->ofps_sent, h);
|
||||
rc->idle_echo_xid = h->xid;
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
*/
|
||||
|
||||
struct vconn;
|
||||
struct ofpstat;
|
||||
|
||||
struct rconn *rconn_new(const char *name,
|
||||
int inactivity_probe_interval, int max_backoff);
|
||||
@@ -92,5 +93,7 @@ unsigned long int rconn_get_total_time_connected(const struct rconn *);
|
||||
int rconn_get_backoff(const struct rconn *);
|
||||
unsigned int rconn_get_state_elapsed(const struct rconn *);
|
||||
unsigned int rconn_get_connection_seqno(const struct rconn *);
|
||||
void rconn_update_protocol_stat(struct rconn *,
|
||||
struct ofpstat *, struct ofpstat *);
|
||||
|
||||
#endif /* rconn.h */
|
||||
@@ -38,6 +38,8 @@
|
||||
* OpenFlow device. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include "ofpstat.h"
|
||||
#include "vconn.h"
|
||||
|
||||
/* Active virtual connection to an OpenFlow device. */
|
||||
@@ -54,6 +56,8 @@ struct vconn {
|
||||
uint32_t ip;
|
||||
char *name;
|
||||
bool reconnectable;
|
||||
struct ofpstat ofps_rcvd;
|
||||
struct ofpstat ofps_sent;
|
||||
};
|
||||
|
||||
void vconn_init(struct vconn *, struct vconn_class *, int connect_status,
|
||||
|
||||
+10
@@ -308,6 +308,8 @@ vcs_send_hello(struct vconn *vconn)
|
||||
make_openflow(sizeof(struct ofp_header), OFPT_HELLO, &b);
|
||||
retval = do_send(vconn, b);
|
||||
if (!retval) {
|
||||
++vconn->ofps_sent.ofps_total;
|
||||
++vconn->ofps_sent.ofps_hello;
|
||||
vconn->state = VCS_RECV_HELLO;
|
||||
} else {
|
||||
ofpbuf_delete(b);
|
||||
@@ -353,6 +355,8 @@ vcs_recv_hello(struct vconn *vconn)
|
||||
OFP_VERSION, oh->version);
|
||||
vconn->state = VCS_CONNECTED;
|
||||
}
|
||||
++vconn->ofps_rcvd.ofps_total;
|
||||
++vconn->ofps_rcvd.ofps_hello;
|
||||
ofpbuf_delete(b);
|
||||
return;
|
||||
} else {
|
||||
@@ -389,6 +393,10 @@ vcs_send_error(struct vconn *vconn)
|
||||
update_openflow_length(b);
|
||||
retval = do_send(vconn, b);
|
||||
if (retval) {
|
||||
++vconn->ofps_sent.ofps_total;
|
||||
++vconn->ofps_sent.ofps_error;
|
||||
++vconn->ofps_sent.ofps_error_type.hello_fail;
|
||||
++vconn->ofps_sent.ofps_error_code.hf_incompat;
|
||||
ofpbuf_delete(b);
|
||||
}
|
||||
if (retval != EAGAIN) {
|
||||
@@ -1138,6 +1146,8 @@ vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status,
|
||||
vconn->ip = ip;
|
||||
vconn->name = xstrdup(name);
|
||||
vconn->reconnectable = reconnectable;
|
||||
memset(&vconn->ofps_rcvd, 0, sizeof(vconn->ofps_rcvd));
|
||||
memset(&vconn->ofps_sent, 0, sizeof(vconn->ofps_sent));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -30,6 +30,7 @@ VLOG_MODULE(pcap)
|
||||
VLOG_MODULE(poll_loop)
|
||||
VLOG_MODULE(port_watcher)
|
||||
VLOG_MODULE(process)
|
||||
VLOG_MODULE(protocol_stat)
|
||||
VLOG_MODULE(secchan)
|
||||
VLOG_MODULE(rconn)
|
||||
VLOG_MODULE(snat)
|
||||
|
||||
Reference in new issue
Block a user