Merge branch 'master' of ../iproute2-next
This commit is contained in:
commit
50cf634899
|
|
@ -0,0 +1,130 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# clang-format configuration file. Intended for clang-format >= 4.
|
||||
#
|
||||
# For more information, see:
|
||||
#
|
||||
# Documentation/process/clang-format.rst
|
||||
# https://clang.llvm.org/docs/ClangFormat.html
|
||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
#
|
||||
---
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
#AfterExternBlock: false # Unknown to clang-format-5.0
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
#SplitEmptyFunction: true # Unknown to clang-format-4.0
|
||||
#SplitEmptyRecord: true # Unknown to clang-format-4.0
|
||||
#SplitEmptyNamespace: true # Unknown to clang-format-4.0
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
#CompactNamespaces: false # Unknown to clang-format-4.0
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
#FixNamespaceComments: false # Unknown to clang-format-4.0
|
||||
|
||||
# Taken from:
|
||||
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
|
||||
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
|
||||
# | sort | uniq
|
||||
ForEachMacros:
|
||||
- 'list_for_each_entry'
|
||||
- 'list_for_each_entry_safe'
|
||||
- 'mnl_attr_for_each_nested'
|
||||
- 'hlist_for_each'
|
||||
- 'hlist_for_each_safe'
|
||||
- 'hlist_for_each_entry'
|
||||
|
||||
#IncludeBlocks: Preserve # Unknown to clang-format-5.0
|
||||
IncludeCategories:
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
#IndentPPDirectives: None # Unknown to clang-format-5.0
|
||||
IndentWidth: 8
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: Inner
|
||||
#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
|
||||
ObjCBlockIndentWidth: 8
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
|
||||
# Taken from git's rules
|
||||
#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
|
||||
PenaltyBreakBeforeFirstCallParameter: 30
|
||||
PenaltyBreakComment: 10
|
||||
PenaltyBreakFirstLessLess: 0
|
||||
PenaltyBreakString: 10
|
||||
PenaltyExcessCharacter: 100
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
#SortUsingDeclarations: false # Unknown to clang-format-4.0
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
|
||||
#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
|
||||
SpaceBeforeParens: ControlStatements
|
||||
#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp03
|
||||
TabWidth: 8
|
||||
UseTab: Always
|
||||
...
|
||||
10
bridge/fdb.c
10
bridge/fdb.c
|
|
@ -39,6 +39,7 @@ static void usage(void)
|
|||
" [ self ] [ master ] [ use ] [ router ] [ extern_learn ]\n"
|
||||
" [ sticky ] [ local | static | dynamic ] [ dst IPADDR ]\n"
|
||||
" [ vlan VID ] [ port PORT] [ vni VNI ] [ via DEV ]\n"
|
||||
" [ src_vni VNI ]\n"
|
||||
" bridge fdb [ show [ br BRDEV ] [ brport DEV ] [ vlan VID ] [ state STATE ] ]\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
|
@ -383,6 +384,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
|
|||
inet_prefix dst;
|
||||
unsigned long port = 0;
|
||||
unsigned long vni = ~0;
|
||||
unsigned long src_vni = ~0;
|
||||
unsigned int via = 0;
|
||||
char *endptr;
|
||||
short vid = -1;
|
||||
|
|
@ -416,6 +418,12 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
|
|||
if ((endptr && *endptr) ||
|
||||
(vni >> 24) || vni == ULONG_MAX)
|
||||
invarg("invalid VNI\n", *argv);
|
||||
} else if (strcmp(*argv, "src_vni") == 0) {
|
||||
NEXT_ARG();
|
||||
src_vni = strtoul(*argv, &endptr, 0);
|
||||
if ((endptr && *endptr) ||
|
||||
(src_vni >> 24) || src_vni == ULONG_MAX)
|
||||
invarg("invalid src VNI\n", *argv);
|
||||
} else if (strcmp(*argv, "via") == 0) {
|
||||
NEXT_ARG();
|
||||
via = ll_name_to_index(*argv);
|
||||
|
|
@ -495,6 +503,8 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
|
|||
}
|
||||
if (vni != ~0)
|
||||
addattr32(&req.n, sizeof(req), NDA_VNI, vni);
|
||||
if (src_vni != ~0)
|
||||
addattr32(&req.n, sizeof(req), NDA_SRC_VNI, src_vni);
|
||||
if (via)
|
||||
addattr32(&req.n, sizeof(req), NDA_IFINDEX, via);
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -272,7 +272,7 @@ const char *bpf_prog_to_default_section(enum bpf_prog_type type);
|
|||
int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv);
|
||||
int bpf_trace_pipe(void);
|
||||
|
||||
void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len);
|
||||
void bpf_print_ops(struct rtattr *bpf_ops, __u16 len);
|
||||
|
||||
int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
|
||||
size_t size_insns, const char *license, char *log,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ unsigned ll_name_to_index(const char *name);
|
|||
const char *ll_index_to_name(unsigned idx);
|
||||
int ll_index_to_type(unsigned idx);
|
||||
int ll_index_to_flags(unsigned idx);
|
||||
void ll_drop_by_index(unsigned index);
|
||||
unsigned namehash(const char *str);
|
||||
|
||||
const char *ll_idx_n2a(unsigned int idx);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
/* Extended instruction set based on top of classic BPF */
|
||||
|
||||
/* instruction classes */
|
||||
#define BPF_JMP32 0x06 /* jmp mode in word width */
|
||||
#define BPF_ALU64 0x07 /* alu mode in double word width */
|
||||
|
||||
/* ld/ldx fields */
|
||||
|
|
@ -266,6 +267,7 @@ enum bpf_attach_type {
|
|||
#define BPF_ANY 0 /* create new element or update existing */
|
||||
#define BPF_NOEXIST 1 /* create new element if it didn't exist */
|
||||
#define BPF_EXIST 2 /* update existing element */
|
||||
#define BPF_F_LOCK 4 /* spin_lock-ed map_lookup/map_update */
|
||||
|
||||
/* flags for BPF_MAP_CREATE command */
|
||||
#define BPF_F_NO_PREALLOC (1U << 0)
|
||||
|
|
@ -2014,6 +2016,19 @@ union bpf_attr {
|
|||
* Only works if *skb* contains an IPv6 packet. Insert a
|
||||
* Segment Routing Header (**struct ipv6_sr_hdr**) inside
|
||||
* the IPv6 header.
|
||||
* **BPF_LWT_ENCAP_IP**
|
||||
* IP encapsulation (GRE/GUE/IPIP/etc). The outer header
|
||||
* must be IPv4 or IPv6, followed by zero or more
|
||||
* additional headers, up to LWT_BPF_MAX_HEADROOM total
|
||||
* bytes in all prepended headers. Please note that
|
||||
* if skb_is_gso(skb) is true, no more than two headers
|
||||
* can be prepended, and the inner header, if present,
|
||||
* should be either GRE or UDP/GUE.
|
||||
*
|
||||
* BPF_LWT_ENCAP_SEG6*** types can be called by bpf programs of
|
||||
* type BPF_PROG_TYPE_LWT_IN; BPF_LWT_ENCAP_IP type can be called
|
||||
* by bpf programs of types BPF_PROG_TYPE_LWT_IN and
|
||||
* BPF_PROG_TYPE_LWT_XMIT.
|
||||
*
|
||||
* A call to this helper is susceptible to change the underlaying
|
||||
* packet buffer. Therefore, at load time, all checks on pointers
|
||||
|
|
@ -2327,6 +2342,23 @@ union bpf_attr {
|
|||
* "**y**".
|
||||
* Return
|
||||
* 0
|
||||
*
|
||||
* struct bpf_sock *bpf_sk_fullsock(struct bpf_sock *sk)
|
||||
* Description
|
||||
* This helper gets a **struct bpf_sock** pointer such
|
||||
* that all the fields in bpf_sock can be accessed.
|
||||
* Return
|
||||
* A **struct bpf_sock** pointer on success, or NULL in
|
||||
* case of failure.
|
||||
*
|
||||
* struct bpf_tcp_sock *bpf_tcp_sock(struct bpf_sock *sk)
|
||||
* Description
|
||||
* This helper gets a **struct bpf_tcp_sock** pointer from a
|
||||
* **struct bpf_sock** pointer.
|
||||
*
|
||||
* Return
|
||||
* A **struct bpf_tcp_sock** pointer on success, or NULL in
|
||||
* case of failure.
|
||||
*/
|
||||
#define __BPF_FUNC_MAPPER(FN) \
|
||||
FN(unspec), \
|
||||
|
|
@ -2421,7 +2453,11 @@ union bpf_attr {
|
|||
FN(map_peek_elem), \
|
||||
FN(msg_push_data), \
|
||||
FN(msg_pop_data), \
|
||||
FN(rc_pointer_rel),
|
||||
FN(rc_pointer_rel), \
|
||||
FN(spin_lock), \
|
||||
FN(spin_unlock), \
|
||||
FN(sk_fullsock), \
|
||||
FN(tcp_sock),
|
||||
|
||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||
* function eBPF program intends to call
|
||||
|
|
@ -2494,7 +2530,8 @@ enum bpf_hdr_start_off {
|
|||
/* Encapsulation type for BPF_FUNC_lwt_push_encap helper. */
|
||||
enum bpf_lwt_encap_mode {
|
||||
BPF_LWT_ENCAP_SEG6,
|
||||
BPF_LWT_ENCAP_SEG6_INLINE
|
||||
BPF_LWT_ENCAP_SEG6_INLINE,
|
||||
BPF_LWT_ENCAP_IP,
|
||||
};
|
||||
|
||||
#define __bpf_md_ptr(type, name) \
|
||||
|
|
@ -2540,6 +2577,8 @@ struct __sk_buff {
|
|||
__bpf_md_ptr(struct bpf_flow_keys *, flow_keys);
|
||||
__u64 tstamp;
|
||||
__u32 wire_len;
|
||||
__u32 gso_segs;
|
||||
__bpf_md_ptr(struct bpf_sock *, sk);
|
||||
};
|
||||
|
||||
struct bpf_tunnel_key {
|
||||
|
|
@ -2581,7 +2620,15 @@ enum bpf_ret_code {
|
|||
BPF_DROP = 2,
|
||||
/* 3-6 reserved */
|
||||
BPF_REDIRECT = 7,
|
||||
/* >127 are reserved for prog type specific return codes */
|
||||
/* >127 are reserved for prog type specific return codes.
|
||||
*
|
||||
* BPF_LWT_REROUTE: used by BPF_PROG_TYPE_LWT_IN and
|
||||
* BPF_PROG_TYPE_LWT_XMIT to indicate that skb had been
|
||||
* changed and should be routed based on its new L3 header.
|
||||
* (This is an L3 redirect, as opposed to L2 redirect
|
||||
* represented by BPF_REDIRECT above).
|
||||
*/
|
||||
BPF_LWT_REROUTE = 128,
|
||||
};
|
||||
|
||||
struct bpf_sock {
|
||||
|
|
@ -2591,14 +2638,52 @@ struct bpf_sock {
|
|||
__u32 protocol;
|
||||
__u32 mark;
|
||||
__u32 priority;
|
||||
__u32 src_ip4; /* Allows 1,2,4-byte read.
|
||||
* Stored in network byte order.
|
||||
/* IP address also allows 1 and 2 bytes access */
|
||||
__u32 src_ip4;
|
||||
__u32 src_ip6[4];
|
||||
__u32 src_port; /* host byte order */
|
||||
__u32 dst_port; /* network byte order */
|
||||
__u32 dst_ip4;
|
||||
__u32 dst_ip6[4];
|
||||
__u32 state;
|
||||
};
|
||||
|
||||
struct bpf_tcp_sock {
|
||||
__u32 snd_cwnd; /* Sending congestion window */
|
||||
__u32 srtt_us; /* smoothed round trip time << 3 in usecs */
|
||||
__u32 rtt_min;
|
||||
__u32 snd_ssthresh; /* Slow start size threshold */
|
||||
__u32 rcv_nxt; /* What we want to receive next */
|
||||
__u32 snd_nxt; /* Next sequence we send */
|
||||
__u32 snd_una; /* First byte we want an ack for */
|
||||
__u32 mss_cache; /* Cached effective mss, not including SACKS */
|
||||
__u32 ecn_flags; /* ECN status bits. */
|
||||
__u32 rate_delivered; /* saved rate sample: packets delivered */
|
||||
__u32 rate_interval_us; /* saved rate sample: time elapsed */
|
||||
__u32 packets_out; /* Packets which are "in flight" */
|
||||
__u32 retrans_out; /* Retransmitted packets out */
|
||||
__u32 total_retrans; /* Total retransmits for entire connection */
|
||||
__u32 segs_in; /* RFC4898 tcpEStatsPerfSegsIn
|
||||
* total number of segments in.
|
||||
*/
|
||||
__u32 src_ip6[4]; /* Allows 1,2,4-byte read.
|
||||
* Stored in network byte order.
|
||||
__u32 data_segs_in; /* RFC4898 tcpEStatsPerfDataSegsIn
|
||||
* total number of data segments in.
|
||||
*/
|
||||
__u32 src_port; /* Allows 4-byte read.
|
||||
* Stored in host byte order
|
||||
__u32 segs_out; /* RFC4898 tcpEStatsPerfSegsOut
|
||||
* The total number of segments sent.
|
||||
*/
|
||||
__u32 data_segs_out; /* RFC4898 tcpEStatsPerfDataSegsOut
|
||||
* total number of data segments sent.
|
||||
*/
|
||||
__u32 lost_out; /* Lost packets */
|
||||
__u32 sacked_out; /* SACK'd packets */
|
||||
__u64 bytes_received; /* RFC4898 tcpEStatsAppHCThruOctetsReceived
|
||||
* sum(delta(rcv_nxt)), or how many bytes
|
||||
* were acked.
|
||||
*/
|
||||
__u64 bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked
|
||||
* sum(delta(snd_una)), or how many bytes
|
||||
* were acked.
|
||||
*/
|
||||
};
|
||||
|
||||
|
|
@ -3054,4 +3139,7 @@ struct bpf_line_info {
|
|||
__u32 line_col;
|
||||
};
|
||||
|
||||
struct bpf_spin_lock {
|
||||
__u32 val;
|
||||
};
|
||||
#endif /* __LINUX_BPF_H__ */
|
||||
|
|
|
|||
|
|
@ -89,6 +89,22 @@ enum devlink_command {
|
|||
DEVLINK_CMD_REGION_DEL,
|
||||
DEVLINK_CMD_REGION_READ,
|
||||
|
||||
DEVLINK_CMD_PORT_PARAM_GET, /* can dump */
|
||||
DEVLINK_CMD_PORT_PARAM_SET,
|
||||
DEVLINK_CMD_PORT_PARAM_NEW,
|
||||
DEVLINK_CMD_PORT_PARAM_DEL,
|
||||
|
||||
DEVLINK_CMD_INFO_GET, /* can dump */
|
||||
|
||||
DEVLINK_CMD_HEALTH_REPORTER_GET,
|
||||
DEVLINK_CMD_HEALTH_REPORTER_SET,
|
||||
DEVLINK_CMD_HEALTH_REPORTER_RECOVER,
|
||||
DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE,
|
||||
DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET,
|
||||
DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,
|
||||
|
||||
DEVLINK_CMD_FLASH_UPDATE,
|
||||
|
||||
/* add new commands above here */
|
||||
__DEVLINK_CMD_MAX,
|
||||
DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
|
||||
|
|
@ -285,6 +301,37 @@ enum devlink_attr {
|
|||
DEVLINK_ATTR_REGION_CHUNK_ADDR, /* u64 */
|
||||
DEVLINK_ATTR_REGION_CHUNK_LEN, /* u64 */
|
||||
|
||||
DEVLINK_ATTR_INFO_DRIVER_NAME, /* string */
|
||||
DEVLINK_ATTR_INFO_SERIAL_NUMBER, /* string */
|
||||
DEVLINK_ATTR_INFO_VERSION_FIXED, /* nested */
|
||||
DEVLINK_ATTR_INFO_VERSION_RUNNING, /* nested */
|
||||
DEVLINK_ATTR_INFO_VERSION_STORED, /* nested */
|
||||
DEVLINK_ATTR_INFO_VERSION_NAME, /* string */
|
||||
DEVLINK_ATTR_INFO_VERSION_VALUE, /* string */
|
||||
|
||||
DEVLINK_ATTR_SB_POOL_CELL_SIZE, /* u32 */
|
||||
|
||||
DEVLINK_ATTR_FMSG, /* nested */
|
||||
DEVLINK_ATTR_FMSG_OBJ_NEST_START, /* flag */
|
||||
DEVLINK_ATTR_FMSG_PAIR_NEST_START, /* flag */
|
||||
DEVLINK_ATTR_FMSG_ARR_NEST_START, /* flag */
|
||||
DEVLINK_ATTR_FMSG_NEST_END, /* flag */
|
||||
DEVLINK_ATTR_FMSG_OBJ_NAME, /* string */
|
||||
DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE, /* u8 */
|
||||
DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA, /* dynamic */
|
||||
|
||||
DEVLINK_ATTR_HEALTH_REPORTER, /* nested */
|
||||
DEVLINK_ATTR_HEALTH_REPORTER_NAME, /* string */
|
||||
DEVLINK_ATTR_HEALTH_REPORTER_STATE, /* u8 */
|
||||
DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT, /* u64 */
|
||||
DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT, /* u64 */
|
||||
DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS, /* u64 */
|
||||
DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD, /* u64 */
|
||||
DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER, /* u8 */
|
||||
|
||||
DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME, /* string */
|
||||
DEVLINK_ATTR_FLASH_UPDATE_COMPONENT, /* string */
|
||||
|
||||
/* add new attributes above here, update the policy in devlink.c */
|
||||
|
||||
__DEVLINK_ATTR_MAX,
|
||||
|
|
|
|||
|
|
@ -108,6 +108,8 @@ struct icmp6hdr {
|
|||
#define ICMPV6_MOBILE_PREFIX_SOL 146
|
||||
#define ICMPV6_MOBILE_PREFIX_ADV 147
|
||||
|
||||
#define ICMPV6_MRDISC_ADV 151
|
||||
|
||||
/*
|
||||
* Codes for Destination Unreachable
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -117,6 +117,30 @@ struct ad_info {
|
|||
__u8 partner_system[ETH_ALEN];
|
||||
};
|
||||
|
||||
/* Embedded inside LINK_XSTATS_TYPE_BOND */
|
||||
enum {
|
||||
BOND_XSTATS_UNSPEC,
|
||||
BOND_XSTATS_3AD,
|
||||
__BOND_XSTATS_MAX
|
||||
};
|
||||
#define BOND_XSTATS_MAX (__BOND_XSTATS_MAX - 1)
|
||||
|
||||
/* Embedded inside BOND_XSTATS_3AD */
|
||||
enum {
|
||||
BOND_3AD_STAT_LACPDU_RX,
|
||||
BOND_3AD_STAT_LACPDU_TX,
|
||||
BOND_3AD_STAT_LACPDU_UNKNOWN_RX,
|
||||
BOND_3AD_STAT_LACPDU_ILLEGAL_RX,
|
||||
BOND_3AD_STAT_MARKER_RX,
|
||||
BOND_3AD_STAT_MARKER_TX,
|
||||
BOND_3AD_STAT_MARKER_RESP_RX,
|
||||
BOND_3AD_STAT_MARKER_RESP_TX,
|
||||
BOND_3AD_STAT_MARKER_UNKNOWN_RX,
|
||||
BOND_3AD_STAT_PAD,
|
||||
__BOND_3AD_STAT_MAX
|
||||
};
|
||||
#define BOND_3AD_STAT_MAX (__BOND_3AD_STAT_MAX - 1)
|
||||
|
||||
#endif /* _LINUX_IF_BONDING_H */
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -923,6 +923,7 @@ enum {
|
|||
enum {
|
||||
LINK_XSTATS_TYPE_UNSPEC,
|
||||
LINK_XSTATS_TYPE_BRIDGE,
|
||||
LINK_XSTATS_TYPE_BOND,
|
||||
__LINK_XSTATS_TYPE_MAX
|
||||
};
|
||||
#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)
|
||||
|
|
|
|||
|
|
@ -292,10 +292,11 @@ struct sockaddr_in {
|
|||
#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000)
|
||||
|
||||
/* Defines for Multicast INADDR */
|
||||
#define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */
|
||||
#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */
|
||||
#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */
|
||||
#define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */
|
||||
#define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */
|
||||
#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */
|
||||
#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */
|
||||
#define INADDR_ALLSNOOPERS_GROUP 0xe000006aU /* 224.0.0.106 */
|
||||
#define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */
|
||||
#endif
|
||||
|
||||
/* <asm/byteorder.h> contains the htonl type stuff.. */
|
||||
|
|
|
|||
|
|
@ -63,12 +63,49 @@ enum {
|
|||
#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
|
||||
#define TC_ACT_EXT_OPCODE_MAX TC_ACT_GOTO_CHAIN
|
||||
|
||||
/* These macros are put here for binary compatibility with userspace apps that
|
||||
* make use of them. For kernel code and new userspace apps, use the TCA_ID_*
|
||||
* versions.
|
||||
*/
|
||||
#define TCA_ACT_GACT 5
|
||||
#define TCA_ACT_IPT 6
|
||||
#define TCA_ACT_PEDIT 7
|
||||
#define TCA_ACT_MIRRED 8
|
||||
#define TCA_ACT_NAT 9
|
||||
#define TCA_ACT_XT 10
|
||||
#define TCA_ACT_SKBEDIT 11
|
||||
#define TCA_ACT_VLAN 12
|
||||
#define TCA_ACT_BPF 13
|
||||
#define TCA_ACT_CONNMARK 14
|
||||
#define TCA_ACT_SKBMOD 15
|
||||
#define TCA_ACT_CSUM 16
|
||||
#define TCA_ACT_TUNNEL_KEY 17
|
||||
#define TCA_ACT_SIMP 22
|
||||
#define TCA_ACT_IFE 25
|
||||
#define TCA_ACT_SAMPLE 26
|
||||
|
||||
/* Action type identifiers*/
|
||||
enum {
|
||||
TCA_ID_UNSPEC=0,
|
||||
TCA_ID_POLICE=1,
|
||||
enum tca_id {
|
||||
TCA_ID_UNSPEC = 0,
|
||||
TCA_ID_POLICE = 1,
|
||||
TCA_ID_GACT = TCA_ACT_GACT,
|
||||
TCA_ID_IPT = TCA_ACT_IPT,
|
||||
TCA_ID_PEDIT = TCA_ACT_PEDIT,
|
||||
TCA_ID_MIRRED = TCA_ACT_MIRRED,
|
||||
TCA_ID_NAT = TCA_ACT_NAT,
|
||||
TCA_ID_XT = TCA_ACT_XT,
|
||||
TCA_ID_SKBEDIT = TCA_ACT_SKBEDIT,
|
||||
TCA_ID_VLAN = TCA_ACT_VLAN,
|
||||
TCA_ID_BPF = TCA_ACT_BPF,
|
||||
TCA_ID_CONNMARK = TCA_ACT_CONNMARK,
|
||||
TCA_ID_SKBMOD = TCA_ACT_SKBMOD,
|
||||
TCA_ID_CSUM = TCA_ACT_CSUM,
|
||||
TCA_ID_TUNNEL_KEY = TCA_ACT_TUNNEL_KEY,
|
||||
TCA_ID_SIMP = TCA_ACT_SIMP,
|
||||
TCA_ID_IFE = TCA_ACT_IFE,
|
||||
TCA_ID_SAMPLE = TCA_ACT_SAMPLE,
|
||||
/* other actions go here */
|
||||
__TCA_ID_MAX=255
|
||||
__TCA_ID_MAX = 255
|
||||
};
|
||||
|
||||
#define TCA_ID_MAX __TCA_ID_MAX
|
||||
|
|
@ -333,12 +370,19 @@ enum {
|
|||
|
||||
/* Basic filter */
|
||||
|
||||
struct tc_basic_pcnt {
|
||||
__u64 rcnt;
|
||||
__u64 rhit;
|
||||
};
|
||||
|
||||
enum {
|
||||
TCA_BASIC_UNSPEC,
|
||||
TCA_BASIC_CLASSID,
|
||||
TCA_BASIC_EMATCHES,
|
||||
TCA_BASIC_ACT,
|
||||
TCA_BASIC_POLICE,
|
||||
TCA_BASIC_PCNT,
|
||||
TCA_BASIC_PAD,
|
||||
__TCA_BASIC_MAX
|
||||
};
|
||||
|
||||
|
|
@ -527,11 +571,17 @@ enum {
|
|||
|
||||
/* Match-all classifier */
|
||||
|
||||
struct tc_matchall_pcnt {
|
||||
__u64 rhit;
|
||||
};
|
||||
|
||||
enum {
|
||||
TCA_MATCHALL_UNSPEC,
|
||||
TCA_MATCHALL_CLASSID,
|
||||
TCA_MATCHALL_ACT,
|
||||
TCA_MATCHALL_FLAGS,
|
||||
TCA_MATCHALL_PCNT,
|
||||
TCA_MATCHALL_PAD,
|
||||
__TCA_MATCHALL_MAX,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -954,7 +954,7 @@ enum {
|
|||
#define TCA_PIE_MAX (__TCA_PIE_MAX - 1)
|
||||
|
||||
struct tc_pie_xstats {
|
||||
__u32 prob; /* current probability */
|
||||
__u64 prob; /* current probability */
|
||||
__u32 delay; /* current delay in ms */
|
||||
__u32 avg_dq_rate; /* current average dq_rate in bits/pie_time */
|
||||
__u32 packets_in; /* total number of packets enqueued */
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@
|
|||
|
||||
typedef __s32 sctp_assoc_t;
|
||||
|
||||
#define SCTP_FUTURE_ASSOC 0
|
||||
#define SCTP_CURRENT_ASSOC 1
|
||||
#define SCTP_ALL_ASSOC 2
|
||||
|
||||
/* The following symbols come from the Sockets API Extensions for
|
||||
* SCTP <draft-ietf-tsvwg-sctpsocket-07.txt>.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_BPF 13
|
||||
|
||||
struct tc_act_bpf {
|
||||
tc_gen;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_CONNMARK 14
|
||||
|
||||
struct tc_connmark {
|
||||
tc_gen;
|
||||
__u16 zone;
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_CSUM 16
|
||||
|
||||
enum {
|
||||
TCA_CSUM_UNSPEC,
|
||||
TCA_CSUM_PARMS,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_GACT 5
|
||||
struct tc_gact {
|
||||
tc_gen;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#include <linux/pkt_cls.h>
|
||||
#include <linux/ife.h>
|
||||
|
||||
#define TCA_ACT_IFE 25
|
||||
/* Flag bits for now just encoding/decoding; mutually exclusive */
|
||||
#define IFE_ENCODE 1
|
||||
#define IFE_DECODE 0
|
||||
|
|
|
|||
|
|
@ -4,9 +4,6 @@
|
|||
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_IPT 6
|
||||
#define TCA_ACT_XT 10
|
||||
|
||||
enum {
|
||||
TCA_IPT_UNSPEC,
|
||||
TCA_IPT_TABLE,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_MIRRED 8
|
||||
#define TCA_EGRESS_REDIR 1 /* packet redirect to EGRESS*/
|
||||
#define TCA_EGRESS_MIRROR 2 /* mirror packet to EGRESS */
|
||||
#define TCA_INGRESS_REDIR 3 /* packet redirect to INGRESS*/
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
#include <linux/pkt_cls.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define TCA_ACT_NAT 9
|
||||
|
||||
enum {
|
||||
TCA_NAT_UNSPEC,
|
||||
TCA_NAT_PARMS,
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_PEDIT 7
|
||||
|
||||
enum {
|
||||
TCA_PEDIT_UNSPEC,
|
||||
TCA_PEDIT_TM,
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@
|
|||
#include <linux/pkt_cls.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#define TCA_ACT_SAMPLE 26
|
||||
|
||||
struct tc_sample {
|
||||
tc_gen;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_SKBEDIT 11
|
||||
|
||||
#define SKBEDIT_F_PRIORITY 0x1
|
||||
#define SKBEDIT_F_QUEUE_MAPPING 0x2
|
||||
#define SKBEDIT_F_MARK 0x4
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_SKBMOD 15
|
||||
|
||||
#define SKBMOD_F_DMAC 0x1
|
||||
#define SKBMOD_F_SMAC 0x2
|
||||
#define SKBMOD_F_ETYPE 0x4
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@
|
|||
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_TUNNEL_KEY 17
|
||||
|
||||
#define TCA_TUNNEL_KEY_ACT_SET 1
|
||||
#define TCA_TUNNEL_KEY_ACT_RELEASE 2
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_VLAN 12
|
||||
|
||||
#define TCA_VLAN_ACT_POP 1
|
||||
#define TCA_VLAN_ACT_PUSH 2
|
||||
#define TCA_VLAN_ACT_MODIFY 3
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* xdp_diag: interface for query/monitor XDP sockets
|
||||
* Copyright(c) 2019 Intel Corporation.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_XDP_DIAG_H
|
||||
#define _LINUX_XDP_DIAG_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct xdp_diag_req {
|
||||
__u8 sdiag_family;
|
||||
__u8 sdiag_protocol;
|
||||
__u16 pad;
|
||||
__u32 xdiag_ino;
|
||||
__u32 xdiag_show;
|
||||
__u32 xdiag_cookie[2];
|
||||
};
|
||||
|
||||
struct xdp_diag_msg {
|
||||
__u8 xdiag_family;
|
||||
__u8 xdiag_type;
|
||||
__u16 pad;
|
||||
__u32 xdiag_ino;
|
||||
__u32 xdiag_cookie[2];
|
||||
};
|
||||
|
||||
#define XDP_SHOW_INFO (1 << 0) /* Basic information */
|
||||
#define XDP_SHOW_RING_CFG (1 << 1)
|
||||
#define XDP_SHOW_UMEM (1 << 2)
|
||||
#define XDP_SHOW_MEMINFO (1 << 3)
|
||||
|
||||
enum {
|
||||
XDP_DIAG_NONE,
|
||||
XDP_DIAG_INFO,
|
||||
XDP_DIAG_UID,
|
||||
XDP_DIAG_RX_RING,
|
||||
XDP_DIAG_TX_RING,
|
||||
XDP_DIAG_UMEM,
|
||||
XDP_DIAG_UMEM_FILL_RING,
|
||||
XDP_DIAG_UMEM_COMPLETION_RING,
|
||||
XDP_DIAG_MEMINFO,
|
||||
__XDP_DIAG_MAX,
|
||||
};
|
||||
|
||||
#define XDP_DIAG_MAX (__XDP_DIAG_MAX - 1)
|
||||
|
||||
struct xdp_diag_info {
|
||||
__u32 ifindex;
|
||||
__u32 queue_id;
|
||||
};
|
||||
|
||||
struct xdp_diag_ring {
|
||||
__u32 entries; /*num descs */
|
||||
};
|
||||
|
||||
#define XDP_DU_F_ZEROCOPY (1 << 0)
|
||||
|
||||
struct xdp_diag_umem {
|
||||
__u64 size;
|
||||
__u32 id;
|
||||
__u32 num_pages;
|
||||
__u32 chunk_size;
|
||||
__u32 headroom;
|
||||
__u32 ifindex;
|
||||
__u32 queue_id;
|
||||
__u32 flags;
|
||||
__u32 refs;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_XDP_DIAG_H */
|
||||
|
|
@ -127,6 +127,14 @@ struct dn_naddr
|
|||
# define CLOCK_TAI 11
|
||||
#endif
|
||||
|
||||
#ifndef AF_XDP
|
||||
# define AF_XDP 44
|
||||
# if AF_MAX < 45
|
||||
# undef AF_MAX
|
||||
# define AF_MAX 45
|
||||
# endif
|
||||
#endif
|
||||
|
||||
__u32 get_addr32(const char *name);
|
||||
int get_addr_1(inet_prefix *dst, const char *arg, int family);
|
||||
int get_prefix_1(inet_prefix *dst, char *arg, int family);
|
||||
|
|
|
|||
|
|
@ -130,6 +130,9 @@ void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len);
|
|||
int bridge_parse_xstats(struct link_util *lu, int argc, char **argv);
|
||||
int bridge_print_xstats(struct nlmsghdr *n, void *arg);
|
||||
|
||||
int bond_parse_xstats(struct link_util *lu, int argc, char **argv);
|
||||
int bond_print_xstats(struct nlmsghdr *n, void *arg);
|
||||
|
||||
/* iproute_lwtunnel.c */
|
||||
int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp);
|
||||
void lwt_print_encap(FILE *fp, struct rtattr *encap_type, struct rtattr *encap);
|
||||
|
|
|
|||
|
|
@ -237,9 +237,9 @@ static void print_tunnel(const struct l2tp_data *data)
|
|||
print_string(PRINT_FP, NULL,
|
||||
" UDP source / dest ports:", NULL);
|
||||
|
||||
print_uint(PRINT_ANY, "local_port", " %hu",
|
||||
print_hu(PRINT_ANY, "local_port", " %hu",
|
||||
p->local_udp_port);
|
||||
print_uint(PRINT_ANY, "peer_port", "/%hu",
|
||||
print_hu(PRINT_ANY, "peer_port", "/%hu",
|
||||
p->peer_udp_port);
|
||||
print_nl();
|
||||
|
||||
|
|
|
|||
|
|
@ -1083,6 +1083,9 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
|
|||
if (rtnl_talk(&rth, &req.n, NULL) < 0)
|
||||
return -2;
|
||||
|
||||
/* remove device from cache; next use can refresh with new data */
|
||||
ll_drop_by_index(req.i.ifi_index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
167
ip/iplink_bond.c
167
ip/iplink_bond.c
|
|
@ -13,16 +13,18 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/if_bonding.h>
|
||||
|
||||
#include "rt_names.h"
|
||||
#include "utils.h"
|
||||
#include "ip_common.h"
|
||||
#include "json_print.h"
|
||||
|
||||
#define BOND_MAX_ARP_TARGETS 16
|
||||
|
||||
static unsigned int xstats_print_attr;
|
||||
static int filter_index;
|
||||
|
||||
static const char *mode_tbl[] = {
|
||||
"balance-rr",
|
||||
"active-backup",
|
||||
|
|
@ -649,10 +651,169 @@ static void bond_print_help(struct link_util *lu, int argc, char **argv,
|
|||
print_explain(f);
|
||||
}
|
||||
|
||||
static void bond_print_xstats_help(struct link_util *lu, FILE *f)
|
||||
{
|
||||
fprintf(f, "Usage: ... %s [ 802.3ad ] [ dev DEVICE ]\n", lu->id);
|
||||
}
|
||||
|
||||
static void bond_print_3ad_stats(struct rtattr *lacpattr)
|
||||
{
|
||||
struct rtattr *lacptb[BOND_3AD_STAT_MAX+1];
|
||||
__u64 val;
|
||||
|
||||
parse_rtattr(lacptb, BOND_3AD_STAT_MAX, RTA_DATA(lacpattr),
|
||||
RTA_PAYLOAD(lacpattr));
|
||||
open_json_object("802.3ad");
|
||||
if (lacptb[BOND_3AD_STAT_LACPDU_RX]) {
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "lacpdu_rx", "LACPDU Rx %llu\n",
|
||||
rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_RX]));
|
||||
}
|
||||
if (lacptb[BOND_3AD_STAT_LACPDU_TX]) {
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "lacpdu_tx", "LACPDU Tx %llu\n",
|
||||
rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_TX]));
|
||||
}
|
||||
if (lacptb[BOND_3AD_STAT_LACPDU_UNKNOWN_RX]) {
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
val = rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_UNKNOWN_RX]);
|
||||
print_u64(PRINT_ANY,
|
||||
"lacpdu_unknown_rx",
|
||||
"LACPDU Unknown type Rx %llu\n",
|
||||
val);
|
||||
}
|
||||
if (lacptb[BOND_3AD_STAT_LACPDU_ILLEGAL_RX]) {
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
val = rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_ILLEGAL_RX]);
|
||||
print_u64(PRINT_ANY,
|
||||
"lacpdu_illegal_rx",
|
||||
"LACPDU Illegal Rx %llu\n",
|
||||
val);
|
||||
}
|
||||
if (lacptb[BOND_3AD_STAT_MARKER_RX]) {
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "marker_rx", "Marker Rx %llu\n",
|
||||
rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RX]));
|
||||
}
|
||||
if (lacptb[BOND_3AD_STAT_MARKER_TX]) {
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "marker_tx", "Marker Tx %llu\n",
|
||||
rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_TX]));
|
||||
}
|
||||
if (lacptb[BOND_3AD_STAT_MARKER_RESP_RX]) {
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RESP_RX]);
|
||||
print_u64(PRINT_ANY,
|
||||
"marker_response_rx",
|
||||
"Marker response Rx %llu\n",
|
||||
val);
|
||||
}
|
||||
if (lacptb[BOND_3AD_STAT_MARKER_RESP_TX]) {
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RESP_TX]);
|
||||
print_u64(PRINT_ANY,
|
||||
"marker_response_tx",
|
||||
"Marker response Tx %llu\n",
|
||||
val);
|
||||
}
|
||||
if (lacptb[BOND_3AD_STAT_MARKER_UNKNOWN_RX]) {
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_UNKNOWN_RX]);
|
||||
print_u64(PRINT_ANY,
|
||||
"marker_unknown_rx",
|
||||
"Marker unknown type Rx %llu\n",
|
||||
val);
|
||||
}
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
static void bond_print_stats_attr(struct rtattr *attr, int ifindex)
|
||||
{
|
||||
struct rtattr *bondtb[LINK_XSTATS_TYPE_MAX+1];
|
||||
struct rtattr *i, *list;
|
||||
const char *ifname = "";
|
||||
int rem;
|
||||
|
||||
parse_rtattr(bondtb, LINK_XSTATS_TYPE_MAX+1, RTA_DATA(attr),
|
||||
RTA_PAYLOAD(attr));
|
||||
if (!bondtb[LINK_XSTATS_TYPE_BOND])
|
||||
return;
|
||||
|
||||
list = bondtb[LINK_XSTATS_TYPE_BOND];
|
||||
rem = RTA_PAYLOAD(list);
|
||||
open_json_object(NULL);
|
||||
ifname = ll_index_to_name(ifindex);
|
||||
print_string(PRINT_ANY, "ifname", "%-16s\n", ifname);
|
||||
for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||
if (xstats_print_attr && i->rta_type != xstats_print_attr)
|
||||
continue;
|
||||
|
||||
switch (i->rta_type) {
|
||||
case BOND_XSTATS_3AD:
|
||||
bond_print_3ad_stats(i);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
int bond_print_xstats(struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
struct if_stats_msg *ifsm = NLMSG_DATA(n);
|
||||
struct rtattr *tb[IFLA_STATS_MAX+1];
|
||||
int len = n->nlmsg_len;
|
||||
|
||||
len -= NLMSG_LENGTH(sizeof(*ifsm));
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
|
||||
return -1;
|
||||
}
|
||||
if (filter_index && filter_index != ifsm->ifindex)
|
||||
return 0;
|
||||
|
||||
parse_rtattr(tb, IFLA_STATS_MAX, IFLA_STATS_RTA(ifsm), len);
|
||||
if (tb[IFLA_STATS_LINK_XSTATS])
|
||||
bond_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS],
|
||||
ifsm->ifindex);
|
||||
|
||||
if (tb[IFLA_STATS_LINK_XSTATS_SLAVE])
|
||||
bond_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS_SLAVE],
|
||||
ifsm->ifindex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bond_parse_xstats(struct link_util *lu, int argc, char **argv)
|
||||
{
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "lacp") == 0 ||
|
||||
strcmp(*argv, "802.3ad") == 0) {
|
||||
xstats_print_attr = BOND_XSTATS_3AD;
|
||||
} else if (strcmp(*argv, "dev") == 0) {
|
||||
NEXT_ARG();
|
||||
filter_index = ll_name_to_index(*argv);
|
||||
if (!filter_index)
|
||||
return nodev(*argv);
|
||||
} else if (strcmp(*argv, "help") == 0) {
|
||||
bond_print_xstats_help(lu, stdout);
|
||||
exit(0);
|
||||
} else {
|
||||
invarg("unknown attribute", *argv);
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct link_util bond_link_util = {
|
||||
.id = "bond",
|
||||
.maxattr = IFLA_BOND_MAX,
|
||||
.parse_opt = bond_parse_opt,
|
||||
.print_opt = bond_print_opt,
|
||||
.print_help = bond_print_help,
|
||||
.parse_ifla_xstats = bond_parse_xstats,
|
||||
.print_ifla_xstats = bond_print_xstats,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -156,4 +156,6 @@ struct link_util bond_slave_link_util = {
|
|||
.print_opt = bond_slave_print_opt,
|
||||
.parse_opt = bond_slave_parse_opt,
|
||||
.print_help = bond_slave_print_help,
|
||||
.parse_ifla_xstats = bond_parse_xstats,
|
||||
.print_ifla_xstats = bond_print_xstats,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -670,7 +670,7 @@ static void bridge_print_xstats_help(struct link_util *lu, FILE *f)
|
|||
fprintf(f, "Usage: ... %s [ igmp ] [ dev DEVICE ]\n", lu->id);
|
||||
}
|
||||
|
||||
static void bridge_print_stats_attr(FILE *f, struct rtattr *attr, int ifindex)
|
||||
static void bridge_print_stats_attr(struct rtattr *attr, int ifindex)
|
||||
{
|
||||
struct rtattr *brtb[LINK_XSTATS_TYPE_MAX+1];
|
||||
struct br_mcast_stats *mstats;
|
||||
|
|
@ -685,76 +685,116 @@ static void bridge_print_stats_attr(FILE *f, struct rtattr *attr, int ifindex)
|
|||
|
||||
list = brtb[LINK_XSTATS_TYPE_BRIDGE];
|
||||
rem = RTA_PAYLOAD(list);
|
||||
open_json_object(NULL);
|
||||
ifname = ll_index_to_name(ifindex);
|
||||
print_string(PRINT_ANY, "ifname", "%-16s\n", ifname);
|
||||
for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||
if (xstats_print_attr && i->rta_type != xstats_print_attr)
|
||||
continue;
|
||||
switch (i->rta_type) {
|
||||
case BRIDGE_XSTATS_MCAST:
|
||||
mstats = RTA_DATA(i);
|
||||
ifname = ll_index_to_name(ifindex);
|
||||
fprintf(f, "%-16s\n", ifname);
|
||||
fprintf(f, "%-16s IGMP queries:\n", "");
|
||||
fprintf(f, "%-16s RX: v1 %llu v2 %llu v3 %llu\n",
|
||||
"",
|
||||
mstats->igmp_v1queries[BR_MCAST_DIR_RX],
|
||||
mstats->igmp_v2queries[BR_MCAST_DIR_RX],
|
||||
mstats->igmp_v3queries[BR_MCAST_DIR_RX]);
|
||||
fprintf(f, "%-16s TX: v1 %llu v2 %llu v3 %llu\n",
|
||||
"",
|
||||
mstats->igmp_v1queries[BR_MCAST_DIR_TX],
|
||||
mstats->igmp_v2queries[BR_MCAST_DIR_TX],
|
||||
mstats->igmp_v3queries[BR_MCAST_DIR_TX]);
|
||||
open_json_object("multicast");
|
||||
open_json_object("igmp_queries");
|
||||
print_string(PRINT_FP, NULL,
|
||||
"%-16s IGMP queries:\n", "");
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ",
|
||||
mstats->igmp_v1queries[BR_MCAST_DIR_RX]);
|
||||
print_u64(PRINT_ANY, "rx_v2", "v2 %llu ",
|
||||
mstats->igmp_v2queries[BR_MCAST_DIR_RX]);
|
||||
print_u64(PRINT_ANY, "rx_v3", "v3 %llu\n",
|
||||
mstats->igmp_v3queries[BR_MCAST_DIR_RX]);
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ",
|
||||
mstats->igmp_v1queries[BR_MCAST_DIR_TX]);
|
||||
print_u64(PRINT_ANY, "tx_v2", "v2 %llu ",
|
||||
mstats->igmp_v2queries[BR_MCAST_DIR_TX]);
|
||||
print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n",
|
||||
mstats->igmp_v3queries[BR_MCAST_DIR_TX]);
|
||||
close_json_object();
|
||||
|
||||
fprintf(f, "%-16s IGMP reports:\n", "");
|
||||
fprintf(f, "%-16s RX: v1 %llu v2 %llu v3 %llu\n",
|
||||
"",
|
||||
mstats->igmp_v1reports[BR_MCAST_DIR_RX],
|
||||
mstats->igmp_v2reports[BR_MCAST_DIR_RX],
|
||||
mstats->igmp_v3reports[BR_MCAST_DIR_RX]);
|
||||
fprintf(f, "%-16s TX: v1 %llu v2 %llu v3 %llu\n",
|
||||
"",
|
||||
mstats->igmp_v1reports[BR_MCAST_DIR_TX],
|
||||
mstats->igmp_v2reports[BR_MCAST_DIR_TX],
|
||||
mstats->igmp_v3reports[BR_MCAST_DIR_TX]);
|
||||
open_json_object("igmp_reports");
|
||||
print_string(PRINT_FP, NULL,
|
||||
"%-16s IGMP reports:\n", "");
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ",
|
||||
mstats->igmp_v1reports[BR_MCAST_DIR_RX]);
|
||||
print_u64(PRINT_ANY, "rx_v2", "v2 %llu ",
|
||||
mstats->igmp_v2reports[BR_MCAST_DIR_RX]);
|
||||
print_u64(PRINT_ANY, "rx_v3", "v3 %llu\n",
|
||||
mstats->igmp_v3reports[BR_MCAST_DIR_RX]);
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ",
|
||||
mstats->igmp_v1reports[BR_MCAST_DIR_TX]);
|
||||
print_u64(PRINT_ANY, "tx_v2", "v2 %llu",
|
||||
mstats->igmp_v2reports[BR_MCAST_DIR_TX]);
|
||||
print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n",
|
||||
mstats->igmp_v3reports[BR_MCAST_DIR_TX]);
|
||||
close_json_object();
|
||||
|
||||
fprintf(f, "%-16s IGMP leaves: RX: %llu TX: %llu\n",
|
||||
"",
|
||||
mstats->igmp_leaves[BR_MCAST_DIR_RX],
|
||||
mstats->igmp_leaves[BR_MCAST_DIR_TX]);
|
||||
open_json_object("igmp_leaves");
|
||||
print_string(PRINT_FP, NULL,
|
||||
"%-16s IGMP leaves: ", "");
|
||||
print_u64(PRINT_ANY, "rx", "RX: %llu ",
|
||||
mstats->igmp_leaves[BR_MCAST_DIR_RX]);
|
||||
print_u64(PRINT_ANY, "tx", "TX: %llu\n",
|
||||
mstats->igmp_leaves[BR_MCAST_DIR_TX]);
|
||||
close_json_object();
|
||||
|
||||
fprintf(f, "%-16s IGMP parse errors: %llu\n",
|
||||
"", mstats->igmp_parse_errors);
|
||||
print_string(PRINT_FP, NULL,
|
||||
"%-16s IGMP parse errors: ", "");
|
||||
print_u64(PRINT_ANY, "igmp_parse_errors", "%llu\n",
|
||||
mstats->igmp_parse_errors);
|
||||
|
||||
fprintf(f, "%-16s MLD queries:\n", "");
|
||||
fprintf(f, "%-16s RX: v1 %llu v2 %llu\n",
|
||||
"",
|
||||
mstats->mld_v1queries[BR_MCAST_DIR_RX],
|
||||
mstats->mld_v2queries[BR_MCAST_DIR_RX]);
|
||||
fprintf(f, "%-16s TX: v1 %llu v2 %llu\n",
|
||||
"",
|
||||
mstats->mld_v1queries[BR_MCAST_DIR_TX],
|
||||
mstats->mld_v2queries[BR_MCAST_DIR_TX]);
|
||||
open_json_object("mld_queries");
|
||||
print_string(PRINT_FP, NULL,
|
||||
"%-16s MLD queries:\n", "");
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ",
|
||||
mstats->mld_v1queries[BR_MCAST_DIR_RX]);
|
||||
print_u64(PRINT_ANY, "rx_v2", "v2 %llu\n",
|
||||
mstats->mld_v2queries[BR_MCAST_DIR_RX]);
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ",
|
||||
mstats->mld_v1queries[BR_MCAST_DIR_TX]);
|
||||
print_u64(PRINT_ANY, "tx_v2", "v2 %llu\n",
|
||||
mstats->mld_v2queries[BR_MCAST_DIR_TX]);
|
||||
close_json_object();
|
||||
|
||||
fprintf(f, "%-16s MLD reports:\n", "");
|
||||
fprintf(f, "%-16s RX: v1 %llu v2 %llu\n",
|
||||
"",
|
||||
mstats->mld_v1reports[BR_MCAST_DIR_RX],
|
||||
mstats->mld_v2reports[BR_MCAST_DIR_RX]);
|
||||
fprintf(f, "%-16s TX: v1 %llu v2 %llu\n",
|
||||
"",
|
||||
mstats->mld_v1reports[BR_MCAST_DIR_TX],
|
||||
mstats->mld_v2reports[BR_MCAST_DIR_TX]);
|
||||
open_json_object("mld_reports");
|
||||
print_string(PRINT_FP, NULL,
|
||||
"%-16s MLD reports:\n", "");
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ",
|
||||
mstats->mld_v1reports[BR_MCAST_DIR_RX]);
|
||||
print_u64(PRINT_ANY, "rx_v2", "v2 %llu\n",
|
||||
mstats->mld_v2reports[BR_MCAST_DIR_RX]);
|
||||
print_string(PRINT_FP, NULL, "%-16s ", "");
|
||||
print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ",
|
||||
mstats->mld_v1reports[BR_MCAST_DIR_TX]);
|
||||
print_u64(PRINT_ANY, "tx_v2", "v2 %llu\n",
|
||||
mstats->mld_v2reports[BR_MCAST_DIR_TX]);
|
||||
close_json_object();
|
||||
|
||||
fprintf(f, "%-16s MLD leaves: RX: %llu TX: %llu\n",
|
||||
"",
|
||||
mstats->mld_leaves[BR_MCAST_DIR_RX],
|
||||
mstats->mld_leaves[BR_MCAST_DIR_TX]);
|
||||
open_json_object("mld_leaves");
|
||||
print_string(PRINT_FP, NULL,
|
||||
"%-16s MLD leaves: ", "");
|
||||
print_u64(PRINT_ANY, "rx", "RX: %llu ",
|
||||
mstats->mld_leaves[BR_MCAST_DIR_RX]);
|
||||
print_u64(PRINT_ANY, "tx", "TX: %llu\n",
|
||||
mstats->mld_leaves[BR_MCAST_DIR_TX]);
|
||||
close_json_object();
|
||||
|
||||
fprintf(f, "%-16s MLD parse errors: %llu\n",
|
||||
"", mstats->mld_parse_errors);
|
||||
print_string(PRINT_FP, NULL,
|
||||
"%-16s MLD parse errors: ", "");
|
||||
print_u64(PRINT_ANY, "mld_parse_errors", "%llu\n",
|
||||
mstats->mld_parse_errors);
|
||||
close_json_object();
|
||||
break;
|
||||
}
|
||||
}
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
int bridge_print_xstats(struct nlmsghdr *n, void *arg)
|
||||
|
|
@ -762,7 +802,6 @@ int bridge_print_xstats(struct nlmsghdr *n, void *arg)
|
|||
struct if_stats_msg *ifsm = NLMSG_DATA(n);
|
||||
struct rtattr *tb[IFLA_STATS_MAX+1];
|
||||
int len = n->nlmsg_len;
|
||||
FILE *fp = arg;
|
||||
|
||||
len -= NLMSG_LENGTH(sizeof(*ifsm));
|
||||
if (len < 0) {
|
||||
|
|
@ -774,11 +813,11 @@ int bridge_print_xstats(struct nlmsghdr *n, void *arg)
|
|||
|
||||
parse_rtattr(tb, IFLA_STATS_MAX, IFLA_STATS_RTA(ifsm), len);
|
||||
if (tb[IFLA_STATS_LINK_XSTATS])
|
||||
bridge_print_stats_attr(fp, tb[IFLA_STATS_LINK_XSTATS],
|
||||
bridge_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS],
|
||||
ifsm->ifindex);
|
||||
|
||||
if (tb[IFLA_STATS_LINK_XSTATS_SLAVE])
|
||||
bridge_print_stats_attr(fp, tb[IFLA_STATS_LINK_XSTATS_SLAVE],
|
||||
bridge_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS_SLAVE],
|
||||
ifsm->ifindex);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -70,10 +70,13 @@ int iplink_ifla_xstats(int argc, char **argv)
|
|||
return -1;
|
||||
}
|
||||
|
||||
new_json_obj(json);
|
||||
if (rtnl_dump_filter(&rth, lu->print_ifla_xstats, stdout) < 0) {
|
||||
delete_json_obj();
|
||||
fprintf(stderr, "Dump terminated\n");
|
||||
return -1;
|
||||
}
|
||||
delete_json_obj();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
62
ip/ipnetns.c
62
ip/ipnetns.c
|
|
@ -28,6 +28,7 @@ static int usage(void)
|
|||
{
|
||||
fprintf(stderr, "Usage: ip netns list\n");
|
||||
fprintf(stderr, " ip netns add NAME\n");
|
||||
fprintf(stderr, " ip netns attach NAME PID\n");
|
||||
fprintf(stderr, " ip netns set NAME NETNSID\n");
|
||||
fprintf(stderr, " ip [-all] netns delete [NAME]\n");
|
||||
fprintf(stderr, " ip netns identify [PID]\n");
|
||||
|
|
@ -632,24 +633,40 @@ static int create_netns_dir(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int netns_add(int argc, char **argv)
|
||||
static int netns_add(int argc, char **argv, bool create)
|
||||
{
|
||||
/* This function creates a new network namespace and
|
||||
* a new mount namespace and bind them into a well known
|
||||
* location in the filesystem based on the name provided.
|
||||
*
|
||||
* If create is true, a new namespace will be created,
|
||||
* otherwise an existing one will be attached to the file.
|
||||
*
|
||||
* The mount namespace is created so that any necessary
|
||||
* userspace tweaks like remounting /sys, or bind mounting
|
||||
* a new /etc/resolv.conf can be shared between uers.
|
||||
* a new /etc/resolv.conf can be shared between users.
|
||||
*/
|
||||
char netns_path[PATH_MAX];
|
||||
char netns_path[PATH_MAX], proc_path[PATH_MAX];
|
||||
const char *name;
|
||||
pid_t pid;
|
||||
int fd;
|
||||
int made_netns_run_dir_mount = 0;
|
||||
|
||||
if (argc < 1) {
|
||||
fprintf(stderr, "No netns name specified\n");
|
||||
return -1;
|
||||
if (create) {
|
||||
if (argc < 1) {
|
||||
fprintf(stderr, "No netns name specified\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "No netns name and PID specified\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_s32(&pid, argv[1], 0) || !pid) {
|
||||
fprintf(stderr, "Invalid PID: %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
name = argv[0];
|
||||
|
||||
|
|
@ -689,21 +706,33 @@ static int netns_add(int argc, char **argv)
|
|||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
if (unshare(CLONE_NEWNET) < 0) {
|
||||
fprintf(stderr, "Failed to create a new network namespace \"%s\": %s\n",
|
||||
name, strerror(errno));
|
||||
goto out_delete;
|
||||
|
||||
if (create) {
|
||||
if (unshare(CLONE_NEWNET) < 0) {
|
||||
fprintf(stderr, "Failed to create a new network namespace \"%s\": %s\n",
|
||||
name, strerror(errno));
|
||||
goto out_delete;
|
||||
}
|
||||
|
||||
strcpy(proc_path, "/proc/self/ns/net");
|
||||
} else {
|
||||
snprintf(proc_path, sizeof(proc_path), "/proc/%d/ns/net", pid);
|
||||
}
|
||||
|
||||
/* Bind the netns last so I can watch for it */
|
||||
if (mount("/proc/self/ns/net", netns_path, "none", MS_BIND, NULL) < 0) {
|
||||
fprintf(stderr, "Bind /proc/self/ns/net -> %s failed: %s\n",
|
||||
netns_path, strerror(errno));
|
||||
if (mount(proc_path, netns_path, "none", MS_BIND, NULL) < 0) {
|
||||
fprintf(stderr, "Bind %s -> %s failed: %s\n",
|
||||
proc_path, netns_path, strerror(errno));
|
||||
goto out_delete;
|
||||
}
|
||||
return 0;
|
||||
out_delete:
|
||||
netns_delete(argc, argv);
|
||||
if (create) {
|
||||
netns_delete(argc, argv);
|
||||
} else if (unlink(netns_path) < 0) {
|
||||
fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
|
||||
netns_path, strerror(errno));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -846,7 +875,7 @@ int do_netns(int argc, char **argv)
|
|||
return usage();
|
||||
|
||||
if (matches(*argv, "add") == 0)
|
||||
return netns_add(argc-1, argv+1);
|
||||
return netns_add(argc-1, argv+1, true);
|
||||
|
||||
if (matches(*argv, "set") == 0)
|
||||
return netns_set(argc-1, argv+1);
|
||||
|
|
@ -866,6 +895,9 @@ int do_netns(int argc, char **argv)
|
|||
if (matches(*argv, "monitor") == 0)
|
||||
return netns_monitor(argc-1, argv+1);
|
||||
|
||||
if (matches(*argv, "attach") == 0)
|
||||
return netns_add(argc-1, argv+1, false);
|
||||
|
||||
fprintf(stderr, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv);
|
||||
exit(-1);
|
||||
}
|
||||
|
|
|
|||
49
ip/ipxfrm.c
49
ip/ipxfrm.c
|
|
@ -497,7 +497,8 @@ void xfrm_selector_print(struct xfrm_selector *sel, __u16 family,
|
|||
}
|
||||
|
||||
static void __xfrm_algo_print(struct xfrm_algo *algo, int type, int len,
|
||||
FILE *fp, const char *prefix, int newline)
|
||||
FILE *fp, const char *prefix, int newline,
|
||||
bool nokeys)
|
||||
{
|
||||
int keylen;
|
||||
int i;
|
||||
|
|
@ -521,7 +522,9 @@ static void __xfrm_algo_print(struct xfrm_algo *algo, int type, int len,
|
|||
goto fin;
|
||||
}
|
||||
|
||||
if (keylen > 0) {
|
||||
if (nokeys)
|
||||
fprintf(fp, "<<Keys hidden>>");
|
||||
else if (keylen > 0) {
|
||||
fprintf(fp, "0x");
|
||||
for (i = 0; i < keylen; i++)
|
||||
fprintf(fp, "%.2x", (unsigned char)algo->alg_key[i]);
|
||||
|
|
@ -536,13 +539,13 @@ static void __xfrm_algo_print(struct xfrm_algo *algo, int type, int len,
|
|||
}
|
||||
|
||||
static inline void xfrm_algo_print(struct xfrm_algo *algo, int type, int len,
|
||||
FILE *fp, const char *prefix)
|
||||
FILE *fp, const char *prefix, bool nokeys)
|
||||
{
|
||||
return __xfrm_algo_print(algo, type, len, fp, prefix, 1);
|
||||
return __xfrm_algo_print(algo, type, len, fp, prefix, 1, nokeys);
|
||||
}
|
||||
|
||||
static void xfrm_aead_print(struct xfrm_algo_aead *algo, int len,
|
||||
FILE *fp, const char *prefix)
|
||||
FILE *fp, const char *prefix, bool nokeys)
|
||||
{
|
||||
struct xfrm_algo *base_algo = alloca(sizeof(*base_algo) + algo->alg_key_len / 8);
|
||||
|
||||
|
|
@ -550,7 +553,8 @@ static void xfrm_aead_print(struct xfrm_algo_aead *algo, int len,
|
|||
base_algo->alg_key_len = algo->alg_key_len;
|
||||
memcpy(base_algo->alg_key, algo->alg_key, algo->alg_key_len / 8);
|
||||
|
||||
__xfrm_algo_print(base_algo, XFRMA_ALG_AEAD, len, fp, prefix, 0);
|
||||
__xfrm_algo_print(base_algo, XFRMA_ALG_AEAD, len, fp, prefix, 0,
|
||||
nokeys);
|
||||
|
||||
fprintf(fp, " %d", algo->alg_icv_len);
|
||||
|
||||
|
|
@ -558,7 +562,7 @@ static void xfrm_aead_print(struct xfrm_algo_aead *algo, int len,
|
|||
}
|
||||
|
||||
static void xfrm_auth_trunc_print(struct xfrm_algo_auth *algo, int len,
|
||||
FILE *fp, const char *prefix)
|
||||
FILE *fp, const char *prefix, bool nokeys)
|
||||
{
|
||||
struct xfrm_algo *base_algo = alloca(sizeof(*base_algo) + algo->alg_key_len / 8);
|
||||
|
||||
|
|
@ -566,7 +570,8 @@ static void xfrm_auth_trunc_print(struct xfrm_algo_auth *algo, int len,
|
|||
base_algo->alg_key_len = algo->alg_key_len;
|
||||
memcpy(base_algo->alg_key, algo->alg_key, algo->alg_key_len / 8);
|
||||
|
||||
__xfrm_algo_print(base_algo, XFRMA_ALG_AUTH_TRUNC, len, fp, prefix, 0);
|
||||
__xfrm_algo_print(base_algo, XFRMA_ALG_AUTH_TRUNC, len, fp, prefix, 0,
|
||||
nokeys);
|
||||
|
||||
fprintf(fp, " %d", algo->alg_trunc_len);
|
||||
|
||||
|
|
@ -679,7 +684,7 @@ done:
|
|||
}
|
||||
|
||||
void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
|
||||
FILE *fp, const char *prefix)
|
||||
FILE *fp, const char *prefix, bool nokeys)
|
||||
{
|
||||
if (tb[XFRMA_MARK]) {
|
||||
struct rtattr *rta = tb[XFRMA_MARK];
|
||||
|
|
@ -700,36 +705,36 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
|
|||
if (tb[XFRMA_ALG_AUTH] && !tb[XFRMA_ALG_AUTH_TRUNC]) {
|
||||
struct rtattr *rta = tb[XFRMA_ALG_AUTH];
|
||||
|
||||
xfrm_algo_print(RTA_DATA(rta),
|
||||
XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix);
|
||||
xfrm_algo_print(RTA_DATA(rta), XFRMA_ALG_AUTH, RTA_PAYLOAD(rta),
|
||||
fp, prefix, nokeys);
|
||||
}
|
||||
|
||||
if (tb[XFRMA_ALG_AUTH_TRUNC]) {
|
||||
struct rtattr *rta = tb[XFRMA_ALG_AUTH_TRUNC];
|
||||
|
||||
xfrm_auth_trunc_print(RTA_DATA(rta),
|
||||
RTA_PAYLOAD(rta), fp, prefix);
|
||||
xfrm_auth_trunc_print(RTA_DATA(rta), RTA_PAYLOAD(rta), fp,
|
||||
prefix, nokeys);
|
||||
}
|
||||
|
||||
if (tb[XFRMA_ALG_AEAD]) {
|
||||
struct rtattr *rta = tb[XFRMA_ALG_AEAD];
|
||||
|
||||
xfrm_aead_print(RTA_DATA(rta),
|
||||
RTA_PAYLOAD(rta), fp, prefix);
|
||||
xfrm_aead_print(RTA_DATA(rta), RTA_PAYLOAD(rta), fp, prefix,
|
||||
nokeys);
|
||||
}
|
||||
|
||||
if (tb[XFRMA_ALG_CRYPT]) {
|
||||
struct rtattr *rta = tb[XFRMA_ALG_CRYPT];
|
||||
|
||||
xfrm_algo_print(RTA_DATA(rta),
|
||||
XFRMA_ALG_CRYPT, RTA_PAYLOAD(rta), fp, prefix);
|
||||
xfrm_algo_print(RTA_DATA(rta), XFRMA_ALG_CRYPT,
|
||||
RTA_PAYLOAD(rta), fp, prefix, nokeys);
|
||||
}
|
||||
|
||||
if (tb[XFRMA_ALG_COMP]) {
|
||||
struct rtattr *rta = tb[XFRMA_ALG_COMP];
|
||||
|
||||
xfrm_algo_print(RTA_DATA(rta),
|
||||
XFRMA_ALG_COMP, RTA_PAYLOAD(rta), fp, prefix);
|
||||
xfrm_algo_print(RTA_DATA(rta), XFRMA_ALG_COMP, RTA_PAYLOAD(rta),
|
||||
fp, prefix, nokeys);
|
||||
}
|
||||
|
||||
if (tb[XFRMA_ENCAP]) {
|
||||
|
|
@ -897,7 +902,7 @@ static int xfrm_selector_iszero(struct xfrm_selector *s)
|
|||
|
||||
void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
|
||||
struct rtattr *tb[], FILE *fp, const char *prefix,
|
||||
const char *title)
|
||||
const char *title, bool nokeys)
|
||||
{
|
||||
char buf[STRBUF_SIZE] = {};
|
||||
int force_spi = xfrm_xfrmproto_is_ipsec(xsinfo->id.proto);
|
||||
|
|
@ -943,7 +948,7 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
|
|||
fprintf(fp, " (0x%s)", strxf_mask8(xsinfo->flags));
|
||||
fprintf(fp, "%s", _SL_);
|
||||
|
||||
xfrm_xfrma_print(tb, xsinfo->family, fp, buf);
|
||||
xfrm_xfrma_print(tb, xsinfo->family, fp, buf, nokeys);
|
||||
|
||||
if (!xfrm_selector_iszero(&xsinfo->sel)) {
|
||||
char sbuf[STRBUF_SIZE];
|
||||
|
|
@ -1071,7 +1076,7 @@ void xfrm_policy_info_print(struct xfrm_userpolicy_info *xpinfo,
|
|||
if (show_stats > 0)
|
||||
xfrm_lifetime_print(&xpinfo->lft, &xpinfo->curlft, fp, buf);
|
||||
|
||||
xfrm_xfrma_print(tb, xpinfo->sel.family, fp, buf);
|
||||
xfrm_xfrma_print(tb, xpinfo->sel.family, fp, buf, false);
|
||||
}
|
||||
|
||||
int xfrm_id_parse(xfrm_address_t *saddr, struct xfrm_id *id, __u16 *family,
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ struct xfrm_filter {
|
|||
extern struct xfrm_filter filter;
|
||||
|
||||
int xfrm_state_print(struct nlmsghdr *n, void *arg);
|
||||
int xfrm_state_print_nokeys(struct nlmsghdr *n, void *arg);
|
||||
int xfrm_policy_print(struct nlmsghdr *n, void *arg);
|
||||
int do_xfrm_state(int argc, char **argv);
|
||||
int do_xfrm_policy(int argc, char **argv);
|
||||
|
|
@ -124,10 +125,10 @@ const char *strxf_ptype(__u8 ptype);
|
|||
void xfrm_selector_print(struct xfrm_selector *sel, __u16 family,
|
||||
FILE *fp, const char *prefix);
|
||||
void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
|
||||
FILE *fp, const char *prefix);
|
||||
FILE *fp, const char *prefix, bool nokeys);
|
||||
void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
|
||||
struct rtattr *tb[], FILE *fp, const char *prefix,
|
||||
const char *title);
|
||||
const char *title, bool nokeys);
|
||||
void xfrm_policy_info_print(struct xfrm_userpolicy_info *xpinfo,
|
||||
struct rtattr *tb[], FILE *fp, const char *prefix,
|
||||
const char *title);
|
||||
|
|
|
|||
|
|
@ -35,10 +35,11 @@
|
|||
|
||||
static void usage(void) __attribute__((noreturn));
|
||||
static int listen_all_nsid;
|
||||
static bool nokeys;
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: ip xfrm monitor [all-nsid] [ all | OBJECTS | help ]\n");
|
||||
fprintf(stderr, "Usage: ip xfrm monitor [ nokeys ] [ all-nsid ] [ all | OBJECTS | help ]\n");
|
||||
fprintf(stderr, "OBJECTS := { acquire | expire | SA | aevent | policy | report }\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
|
@ -197,7 +198,7 @@ static int xfrm_report_print(struct nlmsghdr *n, void *arg)
|
|||
|
||||
parse_rtattr(tb, XFRMA_MAX, XFRMREP_RTA(xrep), len);
|
||||
|
||||
xfrm_xfrma_print(tb, family, fp, " ");
|
||||
xfrm_xfrma_print(tb, family, fp, " ", nokeys);
|
||||
|
||||
if (oneline)
|
||||
fprintf(fp, "\n");
|
||||
|
|
@ -352,6 +353,8 @@ int do_xfrm_monitor(int argc, char **argv)
|
|||
if (matches(*argv, "file") == 0) {
|
||||
NEXT_ARG();
|
||||
file = *argv;
|
||||
} else if (strcmp(*argv, "nokeys") == 0) {
|
||||
nokeys = true;
|
||||
} else if (strcmp(*argv, "all") == 0) {
|
||||
/* fall out */
|
||||
} else if (matches(*argv, "all-nsid") == 0) {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,9 @@ static void usage(void)
|
|||
fprintf(stderr, "Usage: ip xfrm state allocspi ID [ mode MODE ] [ mark MARK [ mask MASK ] ]\n");
|
||||
fprintf(stderr, " [ reqid REQID ] [ seq SEQ ] [ min SPI max SPI ]\n");
|
||||
fprintf(stderr, "Usage: ip xfrm state { delete | get } ID [ mark MARK [ mask MASK ] ]\n");
|
||||
fprintf(stderr, "Usage: ip xfrm state { deleteall | list } [ ID ] [ mode MODE ] [ reqid REQID ]\n");
|
||||
fprintf(stderr, "Usage: ip xfrm state deleteall [ ID ] [ mode MODE ] [ reqid REQID ]\n");
|
||||
fprintf(stderr, " [ flag FLAG-LIST ]\n");
|
||||
fprintf(stderr, "Usage: ip xfrm state list [ nokeys ] [ ID ] [ mode MODE ] [ reqid REQID ]\n");
|
||||
fprintf(stderr, " [ flag FLAG-LIST ]\n");
|
||||
fprintf(stderr, "Usage: ip xfrm state flush [ proto XFRM-PROTO ]\n");
|
||||
fprintf(stderr, "Usage: ip xfrm state count\n");
|
||||
|
|
@ -908,7 +910,7 @@ static int xfrm_state_filter_match(struct xfrm_usersa_info *xsinfo)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int xfrm_state_print(struct nlmsghdr *n, void *arg)
|
||||
static int __do_xfrm_state_print(struct nlmsghdr *n, void *arg, bool nokeys)
|
||||
{
|
||||
FILE *fp = (FILE *)arg;
|
||||
struct rtattr *tb[XFRMA_MAX+1];
|
||||
|
|
@ -979,7 +981,7 @@ int xfrm_state_print(struct nlmsghdr *n, void *arg)
|
|||
xsinfo = RTA_DATA(tb[XFRMA_SA]);
|
||||
}
|
||||
|
||||
xfrm_state_info_print(xsinfo, tb, fp, NULL, NULL);
|
||||
xfrm_state_info_print(xsinfo, tb, fp, NULL, NULL, nokeys);
|
||||
|
||||
if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
|
||||
fprintf(fp, "\t");
|
||||
|
|
@ -994,6 +996,16 @@ int xfrm_state_print(struct nlmsghdr *n, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int xfrm_state_print(struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
return __do_xfrm_state_print(n, arg, false);
|
||||
}
|
||||
|
||||
int xfrm_state_print_nokeys(struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
return __do_xfrm_state_print(n, arg, true);
|
||||
}
|
||||
|
||||
static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
|
||||
{
|
||||
struct rtnl_handle rth;
|
||||
|
|
@ -1145,13 +1157,16 @@ static int xfrm_state_list_or_deleteall(int argc, char **argv, int deleteall)
|
|||
{
|
||||
char *idp = NULL;
|
||||
struct rtnl_handle rth;
|
||||
bool nokeys = false;
|
||||
|
||||
if (argc > 0)
|
||||
filter.use = 1;
|
||||
filter.xsinfo.family = preferred_family;
|
||||
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "mode") == 0) {
|
||||
if (strcmp(*argv, "nokeys") == 0) {
|
||||
nokeys = true;
|
||||
} else if (strcmp(*argv, "mode") == 0) {
|
||||
NEXT_ARG();
|
||||
xfrm_mode_parse(&filter.xsinfo.mode, &argc, &argv);
|
||||
|
||||
|
|
@ -1267,7 +1282,9 @@ static int xfrm_state_list_or_deleteall(int argc, char **argv, int deleteall)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (rtnl_dump_filter(&rth, xfrm_state_print, stdout) < 0) {
|
||||
rtnl_filter_t filter = nokeys ?
|
||||
xfrm_state_print_nokeys : xfrm_state_print;
|
||||
if (rtnl_dump_filter(&rth, filter, stdout) < 0) {
|
||||
fprintf(stderr, "Dump terminated\n");
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
|||
24
lib/bpf.c
24
lib/bpf.c
|
|
@ -339,7 +339,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
|
||||
void bpf_print_ops(struct rtattr *bpf_ops, __u16 len)
|
||||
{
|
||||
struct sock_filter *ops = RTA_DATA(bpf_ops);
|
||||
int i;
|
||||
|
|
@ -347,14 +347,24 @@ void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
|
|||
if (len == 0)
|
||||
return;
|
||||
|
||||
fprintf(f, "bytecode \'%u,", len);
|
||||
open_json_object("bytecode");
|
||||
print_uint(PRINT_ANY, "length", "bytecode \'%u,", len);
|
||||
open_json_array(PRINT_JSON, "insns");
|
||||
|
||||
for (i = 0; i < len - 1; i++)
|
||||
fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt,
|
||||
ops[i].jf, ops[i].k);
|
||||
for (i = 0; i < len; i++) {
|
||||
open_json_object(NULL);
|
||||
print_hu(PRINT_ANY, "code", "%hu ", ops[i].code);
|
||||
print_hhu(PRINT_ANY, "jt", "%hhu ", ops[i].jt);
|
||||
print_hhu(PRINT_ANY, "jf", "%hhu ", ops[i].jf);
|
||||
if (i == len - 1)
|
||||
print_uint(PRINT_ANY, "k", "%u\'", ops[i].k);
|
||||
else
|
||||
print_uint(PRINT_ANY, "k", "%u,", ops[i].k);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
fprintf(f, "%hu %hhu %hhu %u\'", ops[i].code, ops[i].jt,
|
||||
ops[i].jf, ops[i].k);
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
static void bpf_map_pin_report(const struct bpf_elf_map *pin,
|
||||
|
|
|
|||
66
lib/ll_map.c
66
lib/ll_map.c
|
|
@ -152,6 +152,48 @@ static unsigned int ll_idx_a2n(const char *name)
|
|||
return idx;
|
||||
}
|
||||
|
||||
static int ll_link_get(const char *name, int index)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct ifinfomsg ifm;
|
||||
char buf[1024];
|
||||
} req = {
|
||||
.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
|
||||
.n.nlmsg_flags = NLM_F_REQUEST,
|
||||
.n.nlmsg_type = RTM_GETLINK,
|
||||
.ifm.ifi_index = index,
|
||||
};
|
||||
__u32 filt_mask = RTEXT_FILTER_VF | RTEXT_FILTER_SKIP_STATS;
|
||||
struct rtnl_handle rth = {};
|
||||
struct nlmsghdr *answer;
|
||||
int rc = 0;
|
||||
|
||||
if (rtnl_open(&rth, 0) < 0)
|
||||
return 0;
|
||||
|
||||
addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
|
||||
if (name)
|
||||
addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name,
|
||||
strlen(name) + 1);
|
||||
|
||||
if (rtnl_talk(&rth, &req.n, &answer) < 0)
|
||||
goto out;
|
||||
|
||||
/* add entry to cache */
|
||||
rc = ll_remember_index(answer, NULL);
|
||||
if (!rc) {
|
||||
struct ifinfomsg *ifm = NLMSG_DATA(answer);
|
||||
|
||||
rc = ifm->ifi_index;
|
||||
}
|
||||
|
||||
free(answer);
|
||||
out:
|
||||
rtnl_close(&rth);
|
||||
return rc;
|
||||
}
|
||||
|
||||
const char *ll_index_to_name(unsigned int idx)
|
||||
{
|
||||
static char buf[IFNAMSIZ];
|
||||
|
|
@ -164,6 +206,12 @@ const char *ll_index_to_name(unsigned int idx)
|
|||
if (im)
|
||||
return im->name;
|
||||
|
||||
if (ll_link_get(NULL, idx) == idx) {
|
||||
im = ll_get_by_index(idx);
|
||||
if (im)
|
||||
return im->name;
|
||||
}
|
||||
|
||||
if (if_indextoname(idx, buf) == NULL)
|
||||
snprintf(buf, IFNAMSIZ, "if%u", idx);
|
||||
|
||||
|
|
@ -204,12 +252,28 @@ unsigned ll_name_to_index(const char *name)
|
|||
if (im)
|
||||
return im->index;
|
||||
|
||||
idx = if_nametoindex(name);
|
||||
idx = ll_link_get(name, 0);
|
||||
if (idx == 0)
|
||||
idx = if_nametoindex(name);
|
||||
if (idx == 0)
|
||||
idx = ll_idx_a2n(name);
|
||||
return idx;
|
||||
}
|
||||
|
||||
void ll_drop_by_index(unsigned index)
|
||||
{
|
||||
struct ll_cache *im;
|
||||
|
||||
im = ll_get_by_index(index);
|
||||
if (!im)
|
||||
return;
|
||||
|
||||
hlist_del(&im->idx_hash);
|
||||
hlist_del(&im->name_hash);
|
||||
|
||||
free(im);
|
||||
}
|
||||
|
||||
void ll_init_map(struct rtnl_handle *rth)
|
||||
{
|
||||
static int initialized;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ bridge \- show / manipulate bridge addresses and devices
|
|||
.BR self " ] [ " master " ] [ " router " ] [ " use " ] [ " extern_learn " ] [ " sticky " ] [ "
|
||||
.B dst
|
||||
.IR IPADDR " ] [ "
|
||||
.B src_vni
|
||||
.IR SRC_VNI " ] ["
|
||||
.B vni
|
||||
.IR VNI " ] ["
|
||||
.B port
|
||||
|
|
@ -473,6 +475,13 @@ is of type VXLAN.
|
|||
the IP address of the destination
|
||||
VXLAN tunnel endpoint where the Ethernet MAC ADDRESS resides.
|
||||
|
||||
.TP
|
||||
.BI src_vni " SRC VNI"
|
||||
the src VNI Network Identifier (or VXLAN Segment ID)
|
||||
this entry belongs to. Used only when the vxlan device is in
|
||||
external or collect metadata mode. If omitted the value specified at
|
||||
vxlan device creation will be used.
|
||||
|
||||
.TP
|
||||
.BI vni " VNI"
|
||||
the VXLAN VNI Network Identifier (or VXLAN Segment ID)
|
||||
|
|
|
|||
|
|
@ -63,6 +63,22 @@ devlink-dev \- devlink device configuration
|
|||
.BR "devlink dev reload"
|
||||
.IR DEV
|
||||
|
||||
.ti -8
|
||||
.BR "devlink dev info"
|
||||
.RI "[ "
|
||||
.IR DEV
|
||||
.RI "]"
|
||||
|
||||
.ti -8
|
||||
.BR "devlink dev flash"
|
||||
.IR DEV
|
||||
.BR file
|
||||
.IR PATH
|
||||
.RI "["
|
||||
.BR target
|
||||
.IR ID
|
||||
.RI "]"
|
||||
|
||||
.SH "DESCRIPTION"
|
||||
.SS devlink dev show - display devlink device attributes
|
||||
|
||||
|
|
@ -151,6 +167,48 @@ If this argument is omitted all parameters supported by devlink devices are list
|
|||
.I "DEV"
|
||||
- Specifies the devlink device to reload.
|
||||
|
||||
.SS devlink dev info - display device information.
|
||||
Display device information provided by the driver. This command can be used
|
||||
to query versions of the hardware components or device components which
|
||||
can't be updated (
|
||||
.I fixed
|
||||
) as well as device firmware which can be updated. For firmware components
|
||||
.I running
|
||||
displays the versions of firmware currently loaded into the device, while
|
||||
.I stored
|
||||
reports the versions in device's flash.
|
||||
.I Running
|
||||
and
|
||||
.I stored
|
||||
versions may differ after flash has been updated, but before reboot.
|
||||
|
||||
.PP
|
||||
.I "DEV"
|
||||
- specifies the devlink device to show.
|
||||
If this argument is omitted all devices are listed.
|
||||
|
||||
.SS devlink dev flash - write device's non-volatile memory.
|
||||
|
||||
.PP
|
||||
.I "DEV"
|
||||
- specifies the devlink device to write to.
|
||||
|
||||
.BR file
|
||||
.I PATH
|
||||
- Path to the file which will be written into device's flash. The path needs
|
||||
to be relative to one of the directories searched by the kernel firmware loaded,
|
||||
such as /lib/firmware.
|
||||
|
||||
.BR component
|
||||
.I NAME
|
||||
- If device stores multiple firmware images in non-volatile memory, this
|
||||
parameter may be used to indicate which firmware image should be written.
|
||||
The value of
|
||||
.I NAME
|
||||
should match the component names from
|
||||
.B "devlink dev info"
|
||||
and may be driver-dependent.
|
||||
|
||||
.SH "EXAMPLES"
|
||||
.PP
|
||||
devlink dev show
|
||||
|
|
|
|||
|
|
@ -0,0 +1,197 @@
|
|||
.TH DEVLINK\-HEALTH 8 "20 Feb 2019" "iproute2" "Linux"
|
||||
.SH NAME
|
||||
devlink-health \- devlink health reporting and recovery
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
.ad l
|
||||
.in +8
|
||||
.ti -8
|
||||
.B devlink
|
||||
.RI "[ " OPTIONS " ]"
|
||||
.B health
|
||||
.RI " { " COMMAND " | "
|
||||
.BR help " }"
|
||||
.sp
|
||||
|
||||
.ti -8
|
||||
.IR OPTIONS " := { "
|
||||
\fB\-V\fR[\fIersion\fR] }
|
||||
|
||||
.ti -8
|
||||
.BR "devlink health show"
|
||||
.RI "[ " DEV ""
|
||||
.B reporter
|
||||
.RI ""REPORTER " ] "
|
||||
|
||||
.ti -8
|
||||
.BR "devlink health recover"
|
||||
.RI "" DEV ""
|
||||
.B reporter
|
||||
.RI "" REPORTER ""
|
||||
|
||||
.ti -8
|
||||
.BR "devlink health diagnose"
|
||||
.RI "" DEV ""
|
||||
.B reporter
|
||||
.RI "" REPORTER ""
|
||||
|
||||
.ti -8
|
||||
.BR "devlink health dump show"
|
||||
.RI "" DEV ""
|
||||
.B reporter
|
||||
.RI "" REPORTER ""
|
||||
|
||||
.ti -8
|
||||
.BR "devlink health dump clear"
|
||||
.RI "" DEV ""
|
||||
.B reporter
|
||||
.RI "" REPORTER ""
|
||||
|
||||
.ti -8
|
||||
.BR "devlink health set"
|
||||
.RI "" DEV ""
|
||||
.B reporter
|
||||
.RI "" REPORTER ""
|
||||
.RI " { "
|
||||
.B grace_period | auto_recover
|
||||
.RI " } { "
|
||||
.RI "" msec ""
|
||||
.RI "|"
|
||||
.RI "" boolean ""
|
||||
.RI " } "
|
||||
.ti -8
|
||||
.B devlink health help
|
||||
|
||||
.SH "DESCRIPTION"
|
||||
.SS devlink health show - Show status and configuration on all supported reporters on all devlink devices.
|
||||
|
||||
.PP
|
||||
.I "DEV"
|
||||
- specifies the devlink device.
|
||||
|
||||
.PP
|
||||
.I "REPORTER"
|
||||
- specifies the reporter's name registered on the devlink device.
|
||||
|
||||
.SS devlink health recover - Initiate a recovery operation on a reporter.
|
||||
This action performs a recovery and increases the recoveries counter on success.
|
||||
|
||||
.PP
|
||||
.I "DEV"
|
||||
- specifies the devlink device.
|
||||
|
||||
.PP
|
||||
.I "REPORTER"
|
||||
- specifies the reporter's name registered on the devlink device.
|
||||
|
||||
.SS devlink health diagnose - Retrieve diagnostics data on a reporter.
|
||||
|
||||
.PP
|
||||
.I "DEV"
|
||||
- specifies the devlink device.
|
||||
|
||||
.PP
|
||||
.I "REPORTER"
|
||||
- specifies the reporter's name registered on the devlink device.
|
||||
|
||||
.SS devlink health dump show - Display the last saved dump.
|
||||
|
||||
.PD 0
|
||||
.P
|
||||
devlink health saves a single dump per reporter. If an dump is
|
||||
.P
|
||||
not already stored by the Devlink, this command will generate a new
|
||||
.P
|
||||
dump. The dump can be generated either automatically when a
|
||||
.P
|
||||
reporter reports on an error or manually at the user's request.
|
||||
.PD
|
||||
|
||||
.PP
|
||||
.I "DEV"
|
||||
- specifies the devlink device.
|
||||
|
||||
.PP
|
||||
.I "REPORTER"
|
||||
- specifies the reporter's name registered on the devlink device.
|
||||
|
||||
.SS devlink health dump clear - Delete the saved dump.
|
||||
Deleting the saved dump enables a generation of a new dump on
|
||||
.PD 0
|
||||
.P
|
||||
the next "devlink health dump show" command.
|
||||
.PD
|
||||
|
||||
.PP
|
||||
.I "DEV"
|
||||
- specifies the devlink device.
|
||||
|
||||
.PP
|
||||
.I "REPORTER"
|
||||
- specifies the reporter's name registered on the devlink device.
|
||||
|
||||
.SS devlink health set - Enable the user to configure:
|
||||
.PD 0
|
||||
1) grace_period [msec] - Time interval between consecutive auto recoveries.
|
||||
.P
|
||||
2) auto_recover [true/false] - Indicates whether the devlink should execute automatic recover on error.
|
||||
.P
|
||||
Please note that this command is not supported on a reporter which
|
||||
doesn't support a recovery method.
|
||||
.PD
|
||||
|
||||
.PP
|
||||
.I "DEV"
|
||||
- specifies the devlink device.
|
||||
|
||||
.PP
|
||||
.I "REPORTER"
|
||||
- specifies the reporter's name registered on the devlink device.
|
||||
|
||||
.SH "EXAMPLES"
|
||||
.PP
|
||||
devlink health show
|
||||
.RS 4
|
||||
List status and configuration of available reporters on devices.
|
||||
.RE
|
||||
.PP
|
||||
devlink health recover pci/0000:00:09.0 reporter tx
|
||||
.RS 4
|
||||
Initiate recovery on tx reporter registered on pci/0000:00:09.0.
|
||||
.RE
|
||||
.PP
|
||||
devlink health diagnose pci/0000:00:09.0 reporter tx
|
||||
.RS 4
|
||||
List diagnostics data on the specified device and reporter.
|
||||
.RE
|
||||
.PP
|
||||
devlink health dump show pci/0000:00:09.0 reporter tx
|
||||
.RS 4
|
||||
Display the last saved dump on the specified device and reporter.
|
||||
.RE
|
||||
.PP
|
||||
devlink health dump clear pci/0000:00:09.0 reporter tx
|
||||
.RS 4
|
||||
Delete saved dump on the specified device and reporter.
|
||||
.RE
|
||||
.PP
|
||||
devlink health set pci/0000:00:09.0 reporter tx grace_period 3500
|
||||
.RS 4
|
||||
Set time interval between auto recoveries to minimum of 3500 msec on
|
||||
the specified device and reporter.
|
||||
.RE
|
||||
.PP
|
||||
devlink health set pci/0000:00:09.0 reporter tx auto_recover false
|
||||
.RS 4
|
||||
Turn off auto recovery on the specified device and reporter.
|
||||
.RE
|
||||
.SH SEE ALSO
|
||||
.BR devlink (8),
|
||||
.BR devlink-dev (8),
|
||||
.BR devlink-port (8),
|
||||
.BR devlink-param (8),
|
||||
.BR devlink-region (8),
|
||||
.br
|
||||
|
||||
.SH AUTHOR
|
||||
Aya Levin <ayal@mellanox.com>
|
||||
|
|
@ -128,6 +128,16 @@ Behaviour of this argument it the same for every command.
|
|||
- specifies the devlink device to show pools.
|
||||
If this argument is omitted all pools of all devices are listed.
|
||||
|
||||
Display available pools listing their
|
||||
.B type, size, thtype
|
||||
and
|
||||
.B cell_size. cell_size
|
||||
is the allocation granularity of memory within the shared buffer. Drivers
|
||||
may round up, round down or reject
|
||||
.B size
|
||||
passed to the set command if it is not multiple of
|
||||
.B cell_size.
|
||||
|
||||
.SS devlink sb pool set - set attributes of pool
|
||||
|
||||
.PP
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ devlink \- Devlink tool
|
|||
.in +8
|
||||
.ti -8
|
||||
.B devlink
|
||||
.RI "[ " OPTIONS " ] { " dev | port | monitor | sb | resource | region " } { " COMMAND " | "
|
||||
.RI "[ " OPTIONS " ] { " dev | port | monitor | sb | resource | region | health " } { " COMMAND " | "
|
||||
.BR help " }"
|
||||
.sp
|
||||
|
||||
|
|
@ -78,6 +78,10 @@ Turn on verbose output.
|
|||
.B region
|
||||
- devlink address region access
|
||||
|
||||
.TP
|
||||
.B health
|
||||
- devlink reporting and recovery
|
||||
|
||||
.SS
|
||||
.I COMMAND
|
||||
|
||||
|
|
@ -109,6 +113,7 @@ Exit status is 0 if command was successful or a positive integer upon failure.
|
|||
.BR devlink-sb (8),
|
||||
.BR devlink-resource (8),
|
||||
.BR devlink-region (8),
|
||||
.BR devlink-health (8),
|
||||
.br
|
||||
|
||||
.SH REPORTING BUGS
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ ip-netns \- process network namespace management
|
|||
.B ip netns add
|
||||
.I NETNSNAME
|
||||
|
||||
.ti -8
|
||||
.B ip netns attach
|
||||
.I NETNSNAME PID
|
||||
|
||||
.ti -8
|
||||
.B ip [-all] netns del
|
||||
.RI "[ " NETNSNAME " ]"
|
||||
|
|
@ -89,6 +93,12 @@ This command displays all of the network namespaces in /var/run/netns
|
|||
If NAME is available in /var/run/netns/ this command creates a new
|
||||
network namespace and assigns NAME.
|
||||
|
||||
.TP
|
||||
.B ip netns attach NAME PID - create a new named network namespace
|
||||
.sp
|
||||
If NAME is available in /var/run/netns/ this command attaches the network
|
||||
namespace of the process PID to NAME as if it were created with ip netns.
|
||||
|
||||
.TP
|
||||
.B ip [-all] netns delete [ NAME ] - delete the name of a network namespace(s)
|
||||
.sp
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ ip-xfrm \- transform configuration
|
|||
.IR MASK " ] ]"
|
||||
|
||||
.ti -8
|
||||
.BR "ip xfrm state" " { " deleteall " | " list " } ["
|
||||
.BR "ip xfrm state " deleteall " ["
|
||||
.IR ID " ]"
|
||||
.RB "[ " mode
|
||||
.IR MODE " ]"
|
||||
|
|
@ -98,6 +98,17 @@ ip-xfrm \- transform configuration
|
|||
.RB "[ " flag
|
||||
.IR FLAG-LIST " ]"
|
||||
|
||||
.ti -8
|
||||
.BR "ip xfrm state " list " ["
|
||||
.IR ID " ]"
|
||||
.RB "[ " nokeys " ]"
|
||||
.RB "[ " mode
|
||||
.IR MODE " ]"
|
||||
.RB "[ " reqid
|
||||
.IR REQID " ]"
|
||||
.RB "[ " flag
|
||||
.IR FLAG-LIST " ]"
|
||||
|
||||
.ti -8
|
||||
.BR "ip xfrm state flush" " [ " proto
|
||||
.IR XFRM-PROTO " ]"
|
||||
|
|
@ -381,6 +392,8 @@ ip-xfrm \- transform configuration
|
|||
.BR "ip xfrm monitor" " ["
|
||||
.BI all-nsid
|
||||
] [
|
||||
.BI nokeys
|
||||
] [
|
||||
.BI all
|
||||
|
|
||||
.IR LISTofXFRM-OBJECTS " ]"
|
||||
|
|
|
|||
|
|
@ -341,16 +341,19 @@ Display SCTP sockets.
|
|||
.B \-\-vsock
|
||||
Display vsock sockets (alias for -f vsock).
|
||||
.TP
|
||||
.B \-\-xdp
|
||||
Display XDP sockets (alias for -f xdp).
|
||||
.TP
|
||||
.B \-f FAMILY, \-\-family=FAMILY
|
||||
Display sockets of type FAMILY.
|
||||
Currently the following families are supported: unix, inet, inet6, link, netlink, vsock.
|
||||
Currently the following families are supported: unix, inet, inet6, link, netlink, vsock, xdp.
|
||||
.TP
|
||||
.B \-A QUERY, \-\-query=QUERY, \-\-socket=QUERY
|
||||
List of socket tables to dump, separated by commas. The following identifiers
|
||||
are understood: all, inet, tcp, udp, raw, unix, packet, netlink, unix_dgram,
|
||||
unix_stream, unix_seqpacket, packet_raw, packet_dgram, dccp, sctp,
|
||||
vsock_stream, vsock_dgram. Any item in the list may optionally be prefixed by
|
||||
an exclamation mark
|
||||
vsock_stream, vsock_dgram, xdp Any item in the list may optionally be
|
||||
prefixed by an exclamation mark
|
||||
.RB ( ! )
|
||||
to exclude that socket table from being dumped.
|
||||
.TP
|
||||
|
|
|
|||
168
misc/ss.c
168
misc/ss.c
|
|
@ -42,6 +42,7 @@
|
|||
#include <linux/unix_diag.h>
|
||||
#include <linux/netdevice.h> /* for MAX_ADDR_LEN */
|
||||
#include <linux/filter.h>
|
||||
#include <linux/xdp_diag.h>
|
||||
#include <linux/packet_diag.h>
|
||||
#include <linux/netlink_diag.h>
|
||||
#include <linux/sctp.h>
|
||||
|
|
@ -209,6 +210,7 @@ enum {
|
|||
VSOCK_ST_DB,
|
||||
VSOCK_DG_DB,
|
||||
TIPC_DB,
|
||||
XDP_DB,
|
||||
MAX_DB
|
||||
};
|
||||
|
||||
|
|
@ -320,6 +322,10 @@ static const struct filter default_dbs[MAX_DB] = {
|
|||
.states = TIPC_SS_CONN,
|
||||
.families = FAMILY_MASK(AF_TIPC),
|
||||
},
|
||||
[XDP_DB] = {
|
||||
.states = (1 << SS_CLOSE),
|
||||
.families = FAMILY_MASK(AF_XDP),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct filter default_afs[AF_MAX] = {
|
||||
|
|
@ -351,6 +357,10 @@ static const struct filter default_afs[AF_MAX] = {
|
|||
.dbs = (1 << TIPC_DB),
|
||||
.states = TIPC_SS_CONN,
|
||||
},
|
||||
[AF_XDP] = {
|
||||
.dbs = (1 << XDP_DB),
|
||||
.states = (1 << SS_CLOSE),
|
||||
},
|
||||
};
|
||||
|
||||
static int do_default = 1;
|
||||
|
|
@ -377,7 +387,7 @@ static int filter_db_parse(struct filter *f, const char *s)
|
|||
ENTRY(all, UDP_DB, DCCP_DB, TCP_DB, RAW_DB,
|
||||
UNIX_ST_DB, UNIX_DG_DB, UNIX_SQ_DB,
|
||||
PACKET_R_DB, PACKET_DG_DB, NETLINK_DB,
|
||||
SCTP_DB, VSOCK_ST_DB, VSOCK_DG_DB),
|
||||
SCTP_DB, VSOCK_ST_DB, VSOCK_DG_DB, XDP_DB),
|
||||
ENTRY(inet, UDP_DB, DCCP_DB, TCP_DB, SCTP_DB, RAW_DB),
|
||||
ENTRY(udp, UDP_DB),
|
||||
ENTRY(dccp, DCCP_DB),
|
||||
|
|
@ -402,6 +412,7 @@ static int filter_db_parse(struct filter *f, const char *s)
|
|||
ENTRY(v_str, VSOCK_ST_DB), /* alias for vsock_stream */
|
||||
ENTRY(vsock_dgram, VSOCK_DG_DB),
|
||||
ENTRY(v_dgr, VSOCK_DG_DB), /* alias for vsock_dgram */
|
||||
ENTRY(xdp, XDP_DB),
|
||||
#undef ENTRY
|
||||
};
|
||||
bool enable = true;
|
||||
|
|
@ -1352,6 +1363,9 @@ static void sock_state_print(struct sockstat *s)
|
|||
case AF_VSOCK:
|
||||
sock_name = vsock_netid_name(s->type);
|
||||
break;
|
||||
case AF_XDP:
|
||||
sock_name = "xdp";
|
||||
break;
|
||||
default:
|
||||
sock_name = "unknown";
|
||||
}
|
||||
|
|
@ -4095,6 +4109,142 @@ static int packet_show(struct filter *f)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int xdp_stats_print(struct sockstat *s, const struct filter *f)
|
||||
{
|
||||
const char *addr, *port;
|
||||
char q_str[16];
|
||||
|
||||
s->local.family = s->remote.family = AF_XDP;
|
||||
|
||||
if (f->f) {
|
||||
if (run_ssfilter(f->f, s) == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
sock_state_print(s);
|
||||
|
||||
if (s->iface) {
|
||||
addr = xll_index_to_name(s->iface);
|
||||
snprintf(q_str, sizeof(q_str), "q%d", s->lport);
|
||||
port = q_str;
|
||||
sock_addr_print(addr, ":", port, NULL);
|
||||
} else {
|
||||
sock_addr_print("", "*", "", NULL);
|
||||
}
|
||||
|
||||
sock_addr_print("", "*", "", NULL);
|
||||
|
||||
proc_ctx_print(s);
|
||||
|
||||
if (show_details)
|
||||
sock_details_print(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xdp_show_ring(const char *name, struct xdp_diag_ring *ring)
|
||||
{
|
||||
out("\n\t%s(", name);
|
||||
out("entries:%u", ring->entries);
|
||||
out(")");
|
||||
}
|
||||
|
||||
static void xdp_show_umem(struct xdp_diag_umem *umem, struct xdp_diag_ring *fr,
|
||||
struct xdp_diag_ring *cr)
|
||||
{
|
||||
out("\n\tumem(");
|
||||
out("id:%u", umem->id);
|
||||
out(",size:%llu", umem->size);
|
||||
out(",num_pages:%u", umem->num_pages);
|
||||
out(",chunk_size:%u", umem->chunk_size);
|
||||
out(",headroom:%u", umem->headroom);
|
||||
out(",ifindex:%u", umem->ifindex);
|
||||
out(",qid:%u", umem->queue_id);
|
||||
out(",zc:%u", umem->flags & XDP_DU_F_ZEROCOPY);
|
||||
out(",refs:%u", umem->refs);
|
||||
out(")");
|
||||
|
||||
if (fr)
|
||||
xdp_show_ring("fr", fr);
|
||||
if (cr)
|
||||
xdp_show_ring("cr", cr);
|
||||
}
|
||||
|
||||
static int xdp_show_sock(struct nlmsghdr *nlh, void *arg)
|
||||
{
|
||||
struct xdp_diag_ring *rx = NULL, *tx = NULL, *fr = NULL, *cr = NULL;
|
||||
struct xdp_diag_msg *msg = NLMSG_DATA(nlh);
|
||||
struct rtattr *tb[XDP_DIAG_MAX + 1];
|
||||
struct xdp_diag_info *info = NULL;
|
||||
struct xdp_diag_umem *umem = NULL;
|
||||
const struct filter *f = arg;
|
||||
struct sockstat stat = {};
|
||||
|
||||
parse_rtattr(tb, XDP_DIAG_MAX, (struct rtattr *)(msg + 1),
|
||||
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*msg)));
|
||||
|
||||
stat.type = msg->xdiag_type;
|
||||
stat.ino = msg->xdiag_ino;
|
||||
stat.state = SS_CLOSE;
|
||||
stat.sk = cookie_sk_get(&msg->xdiag_cookie[0]);
|
||||
|
||||
if (tb[XDP_DIAG_INFO]) {
|
||||
info = RTA_DATA(tb[XDP_DIAG_INFO]);
|
||||
stat.iface = info->ifindex;
|
||||
stat.lport = info->queue_id;
|
||||
}
|
||||
|
||||
if (tb[XDP_DIAG_UID])
|
||||
stat.uid = rta_getattr_u32(tb[XDP_DIAG_UID]);
|
||||
if (tb[XDP_DIAG_RX_RING])
|
||||
rx = RTA_DATA(tb[XDP_DIAG_RX_RING]);
|
||||
if (tb[XDP_DIAG_TX_RING])
|
||||
tx = RTA_DATA(tb[XDP_DIAG_TX_RING]);
|
||||
if (tb[XDP_DIAG_UMEM])
|
||||
umem = RTA_DATA(tb[XDP_DIAG_UMEM]);
|
||||
if (tb[XDP_DIAG_UMEM_FILL_RING])
|
||||
fr = RTA_DATA(tb[XDP_DIAG_UMEM_FILL_RING]);
|
||||
if (tb[XDP_DIAG_UMEM_COMPLETION_RING])
|
||||
cr = RTA_DATA(tb[XDP_DIAG_UMEM_COMPLETION_RING]);
|
||||
if (tb[XDP_DIAG_MEMINFO]) {
|
||||
__u32 *skmeminfo = RTA_DATA(tb[XDP_DIAG_MEMINFO]);
|
||||
|
||||
stat.rq = skmeminfo[SK_MEMINFO_RMEM_ALLOC];
|
||||
}
|
||||
|
||||
if (xdp_stats_print(&stat, f))
|
||||
return 0;
|
||||
|
||||
if (show_details) {
|
||||
if (rx)
|
||||
xdp_show_ring("rx", rx);
|
||||
if (tx)
|
||||
xdp_show_ring("tx", tx);
|
||||
if (umem)
|
||||
xdp_show_umem(umem, fr, cr);
|
||||
}
|
||||
|
||||
if (show_mem)
|
||||
print_skmeminfo(tb, XDP_DIAG_MEMINFO); // really?
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xdp_show(struct filter *f)
|
||||
{
|
||||
DIAG_REQUEST(req, struct xdp_diag_req r);
|
||||
|
||||
if (!filter_af_get(f, AF_XDP) || !(f->states & (1 << SS_CLOSE)))
|
||||
return 0;
|
||||
|
||||
req.r.sdiag_family = AF_XDP;
|
||||
req.r.xdiag_show = XDP_SHOW_INFO | XDP_SHOW_RING_CFG | XDP_SHOW_UMEM |
|
||||
XDP_SHOW_MEMINFO;
|
||||
|
||||
return handle_netlink_request(f, &req.nlh, sizeof(req), xdp_show_sock);
|
||||
}
|
||||
|
||||
static int netlink_show_one(struct filter *f,
|
||||
int prot, int pid, unsigned int groups,
|
||||
int state, int dst_pid, unsigned int dst_group,
|
||||
|
|
@ -4482,6 +4632,9 @@ static int generic_show_sock(struct nlmsghdr *nlh, void *arg)
|
|||
case AF_VSOCK:
|
||||
ret = vsock_show_sock(nlh, arg);
|
||||
break;
|
||||
case AF_XDP:
|
||||
ret = xdp_show_sock(nlh, arg);
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
|
|
@ -4720,7 +4873,7 @@ static void _usage(FILE *dest)
|
|||
" --tipc display only TIPC sockets\n"
|
||||
" --vsock display only vsock sockets\n"
|
||||
" -f, --family=FAMILY display sockets of type FAMILY\n"
|
||||
" FAMILY := {inet|inet6|link|unix|netlink|vsock|tipc|help}\n"
|
||||
" FAMILY := {inet|inet6|link|unix|netlink|vsock|tipc|xdp|help}\n"
|
||||
"\n"
|
||||
" -K, --kill forcibly close sockets, display what was closed\n"
|
||||
" -H, --no-header Suppress header line\n"
|
||||
|
|
@ -4808,6 +4961,9 @@ static int scan_state(const char *state)
|
|||
|
||||
#define OPT_TOS 259
|
||||
|
||||
/* Values of 'x' are already used so a non-character is used */
|
||||
#define OPT_XDPSOCK 260
|
||||
|
||||
static const struct option long_opts[] = {
|
||||
{ "numeric", 0, 0, 'n' },
|
||||
{ "resolve", 0, 0, 'r' },
|
||||
|
|
@ -4846,6 +5002,7 @@ static const struct option long_opts[] = {
|
|||
{ "tos", 0, 0, OPT_TOS },
|
||||
{ "kill", 0, 0, 'K' },
|
||||
{ "no-header", 0, 0, 'H' },
|
||||
{ "xdp", 0, 0, OPT_XDPSOCK},
|
||||
{ 0 }
|
||||
|
||||
};
|
||||
|
|
@ -4933,6 +5090,9 @@ int main(int argc, char *argv[])
|
|||
case '0':
|
||||
filter_af_set(¤t_filter, AF_PACKET);
|
||||
break;
|
||||
case OPT_XDPSOCK:
|
||||
filter_af_set(¤t_filter, AF_XDP);
|
||||
break;
|
||||
case 'f':
|
||||
if (strcmp(optarg, "inet") == 0)
|
||||
filter_af_set(¤t_filter, AF_INET);
|
||||
|
|
@ -4948,6 +5108,8 @@ int main(int argc, char *argv[])
|
|||
filter_af_set(¤t_filter, AF_TIPC);
|
||||
else if (strcmp(optarg, "vsock") == 0)
|
||||
filter_af_set(¤t_filter, AF_VSOCK);
|
||||
else if (strcmp(optarg, "xdp") == 0)
|
||||
filter_af_set(¤t_filter, AF_XDP);
|
||||
else if (strcmp(optarg, "help") == 0)
|
||||
help();
|
||||
else {
|
||||
|
|
@ -5148,6 +5310,8 @@ int main(int argc, char *argv[])
|
|||
vsock_show(¤t_filter);
|
||||
if (current_filter.dbs & (1<<TIPC_DB))
|
||||
tipc_show(¤t_filter);
|
||||
if (current_filter.dbs & (1<<XDP_DB))
|
||||
xdp_show(¤t_filter);
|
||||
|
||||
if (show_users || show_proc_ctx || show_sock_ctx)
|
||||
user_ent_destroy();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
# SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
include ../config.mk
|
||||
|
||||
TARGETS :=
|
||||
|
|
@ -6,7 +6,8 @@ TARGETS :=
|
|||
ifeq ($(HAVE_MNL),y)
|
||||
CFLAGS += -I./include/uapi/
|
||||
|
||||
RDMA_OBJ = rdma.o utils.o dev.o link.o res.o
|
||||
RDMA_OBJ = rdma.o utils.o dev.o link.o res.o res-pd.o res-mr.o res-cq.o \
|
||||
res-cmid.o res-qp.o
|
||||
|
||||
TARGETS += rdma
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* dev.c RDMA tool
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
enum {
|
||||
RDMA_NL_RDMA_CM = 1,
|
||||
RDMA_NL_IWCM,
|
||||
RDMA_NL_IWCM = 2,
|
||||
RDMA_NL_RSVD,
|
||||
RDMA_NL_LS, /* RDMA Local Services */
|
||||
RDMA_NL_NLDEV, /* RDMA device interface */
|
||||
|
|
@ -14,8 +13,7 @@ enum {
|
|||
};
|
||||
|
||||
enum {
|
||||
RDMA_NL_GROUP_CM = 1,
|
||||
RDMA_NL_GROUP_IWPM,
|
||||
RDMA_NL_GROUP_IWPM = 2,
|
||||
RDMA_NL_GROUP_LS,
|
||||
RDMA_NL_NUM_GROUPS
|
||||
};
|
||||
|
|
@ -24,15 +22,17 @@ enum {
|
|||
#define RDMA_NL_GET_OP(type) (type & ((1 << 10) - 1))
|
||||
#define RDMA_NL_GET_TYPE(client, op) ((client << 10) + op)
|
||||
|
||||
enum {
|
||||
RDMA_NL_RDMA_CM_ID_STATS = 0,
|
||||
RDMA_NL_RDMA_CM_NUM_OPS
|
||||
};
|
||||
/* The minimum version that the iwpm kernel supports */
|
||||
#define IWPM_UABI_VERSION_MIN 3
|
||||
|
||||
/* The latest version that the iwpm kernel supports */
|
||||
#define IWPM_UABI_VERSION 4
|
||||
|
||||
/* iwarp port mapper message flags */
|
||||
enum {
|
||||
RDMA_NL_RDMA_CM_ATTR_SRC_ADDR = 1,
|
||||
RDMA_NL_RDMA_CM_ATTR_DST_ADDR,
|
||||
RDMA_NL_RDMA_CM_NUM_ATTR,
|
||||
|
||||
/* Do not map the port for this IWPM request */
|
||||
IWPM_FLAGS_NO_PORT_MAP = (1 << 0),
|
||||
};
|
||||
|
||||
/* iwarp port mapper op-codes */
|
||||
|
|
@ -45,6 +45,7 @@ enum {
|
|||
RDMA_NL_IWPM_HANDLE_ERR,
|
||||
RDMA_NL_IWPM_MAPINFO,
|
||||
RDMA_NL_IWPM_MAPINFO_NUM,
|
||||
RDMA_NL_IWPM_HELLO,
|
||||
RDMA_NL_IWPM_NUM_OPS
|
||||
};
|
||||
|
||||
|
|
@ -83,20 +84,38 @@ enum {
|
|||
IWPM_NLA_MANAGE_MAPPING_UNSPEC = 0,
|
||||
IWPM_NLA_MANAGE_MAPPING_SEQ,
|
||||
IWPM_NLA_MANAGE_ADDR,
|
||||
IWPM_NLA_MANAGE_MAPPED_LOC_ADDR,
|
||||
IWPM_NLA_MANAGE_FLAGS,
|
||||
IWPM_NLA_MANAGE_MAPPING_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
IWPM_NLA_RMANAGE_MAPPING_UNSPEC = 0,
|
||||
IWPM_NLA_RMANAGE_MAPPING_SEQ,
|
||||
IWPM_NLA_RMANAGE_ADDR,
|
||||
IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR,
|
||||
/* The following maintains bisectability of rdma-core */
|
||||
IWPM_NLA_MANAGE_MAPPED_LOC_ADDR = IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR,
|
||||
IWPM_NLA_RMANAGE_MAPPING_ERR,
|
||||
IWPM_NLA_RMANAGE_MAPPING_MAX
|
||||
};
|
||||
|
||||
#define IWPM_NLA_MANAGE_MAPPING_MAX 3
|
||||
#define IWPM_NLA_QUERY_MAPPING_MAX 4
|
||||
#define IWPM_NLA_MAPINFO_SEND_MAX 3
|
||||
#define IWPM_NLA_REMOVE_MAPPING_MAX 3
|
||||
|
||||
enum {
|
||||
IWPM_NLA_QUERY_MAPPING_UNSPEC = 0,
|
||||
IWPM_NLA_QUERY_MAPPING_SEQ,
|
||||
IWPM_NLA_QUERY_LOCAL_ADDR,
|
||||
IWPM_NLA_QUERY_REMOTE_ADDR,
|
||||
IWPM_NLA_QUERY_FLAGS,
|
||||
IWPM_NLA_QUERY_MAPPING_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
IWPM_NLA_RQUERY_MAPPING_UNSPEC = 0,
|
||||
IWPM_NLA_RQUERY_MAPPING_SEQ,
|
||||
IWPM_NLA_RQUERY_LOCAL_ADDR,
|
||||
IWPM_NLA_RQUERY_REMOTE_ADDR,
|
||||
IWPM_NLA_RQUERY_MAPPED_LOC_ADDR,
|
||||
IWPM_NLA_RQUERY_MAPPED_REM_ADDR,
|
||||
IWPM_NLA_RQUERY_MAPPING_ERR,
|
||||
|
|
@ -114,6 +133,7 @@ enum {
|
|||
IWPM_NLA_MAPINFO_UNSPEC = 0,
|
||||
IWPM_NLA_MAPINFO_LOCAL_ADDR,
|
||||
IWPM_NLA_MAPINFO_MAPPED_ADDR,
|
||||
IWPM_NLA_MAPINFO_FLAGS,
|
||||
IWPM_NLA_MAPINFO_MAX
|
||||
};
|
||||
|
||||
|
|
@ -132,6 +152,12 @@ enum {
|
|||
IWPM_NLA_ERR_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
IWPM_NLA_HELLO_UNSPEC = 0,
|
||||
IWPM_NLA_HELLO_ABI_VERSION,
|
||||
IWPM_NLA_HELLO_MAX
|
||||
};
|
||||
|
||||
/*
|
||||
* Local service operations:
|
||||
* RESOLVE - The client requests the local service to resolve a path.
|
||||
|
|
@ -430,6 +456,16 @@ enum rdma_nldev_attr {
|
|||
RDMA_NLDEV_ATTR_DRIVER_S64, /* s64 */
|
||||
RDMA_NLDEV_ATTR_DRIVER_U64, /* u64 */
|
||||
|
||||
/*
|
||||
* Indexes to get/set secific entry,
|
||||
* for QP use RDMA_NLDEV_ATTR_RES_LQPN
|
||||
*/
|
||||
RDMA_NLDEV_ATTR_RES_PDN, /* u32 */
|
||||
RDMA_NLDEV_ATTR_RES_CQN, /* u32 */
|
||||
RDMA_NLDEV_ATTR_RES_MRN, /* u32 */
|
||||
RDMA_NLDEV_ATTR_RES_CM_IDN, /* u32 */
|
||||
RDMA_NLDEV_ATTR_RES_CTXN, /* u32 */
|
||||
|
||||
/*
|
||||
* Always the end
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* link.c RDMA tool
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* rdma.c RDMA tool
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
|
|
|
|||
24
rdma/rdma.h
24
rdma/rdma.h
|
|
@ -1,11 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/*
|
||||
* rdma.c RDMA tool
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
#ifndef _RDMA_TOOL_H_
|
||||
|
|
@ -35,13 +30,20 @@
|
|||
#define MAX_NUMBER_OF_FILTERS 64
|
||||
struct filters {
|
||||
const char *name;
|
||||
bool is_number;
|
||||
uint8_t is_number:1;
|
||||
uint8_t is_doit:1;
|
||||
};
|
||||
|
||||
struct filter_entry {
|
||||
struct list_head list;
|
||||
char *key;
|
||||
char *value;
|
||||
/*
|
||||
* This field menas that we can try to issue .doit calback
|
||||
* on value above. This value can be converted to integer
|
||||
* with simple atoi(). Otherwise "is_doit" will be false.
|
||||
*/
|
||||
uint8_t is_doit:1;
|
||||
};
|
||||
|
||||
struct dev_map {
|
||||
|
|
@ -106,10 +108,12 @@ struct dev_map *dev_map_lookup(struct rd *rd, bool allow_port_index);
|
|||
/*
|
||||
* Filter manipulation
|
||||
*/
|
||||
bool rd_doit_index(struct rd *rd, uint32_t *idx);
|
||||
int rd_build_filter(struct rd *rd, const struct filters valid_filters[]);
|
||||
bool rd_check_is_filtered(struct rd *rd, const char *key, uint32_t val);
|
||||
bool rd_check_is_string_filtered(struct rd *rd, const char *key, const char *val);
|
||||
bool rd_check_is_key_exist(struct rd *rd, const char *key);
|
||||
bool rd_is_filtered_attr(struct rd *rd, const char *key, uint32_t val,
|
||||
struct nlattr *attr);
|
||||
bool rd_is_string_filtered_attr(struct rd *rd, const char *key, const char *val,
|
||||
struct nlattr *attr);
|
||||
/*
|
||||
* Netlink
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,275 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* res-cmid.c RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
#include "res.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
static void print_qp_type(struct rd *rd, uint32_t val)
|
||||
{
|
||||
if (rd->json_output)
|
||||
jsonw_string_field(rd->jw, "qp-type", qp_types_to_str(val));
|
||||
else
|
||||
pr_out("qp-type %s ", qp_types_to_str(val));
|
||||
}
|
||||
|
||||
static const char *cm_id_state_to_str(uint8_t idx)
|
||||
{
|
||||
static const char *const cm_id_states_str[] = {
|
||||
"IDLE", "ADDR_QUERY", "ADDR_RESOLVED",
|
||||
"ROUTE_QUERY", "ROUTE_RESOLVED", "CONNECT",
|
||||
"DISCONNECT", "ADDR_BOUND", "LISTEN",
|
||||
"DEVICE_REMOVAL", "DESTROYING"
|
||||
};
|
||||
|
||||
if (idx < ARRAY_SIZE(cm_id_states_str))
|
||||
return cm_id_states_str[idx];
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static const char *cm_id_ps_to_str(uint32_t ps)
|
||||
{
|
||||
switch (ps) {
|
||||
case RDMA_PS_IPOIB:
|
||||
return "IPoIB";
|
||||
case RDMA_PS_IB:
|
||||
return "IPoIB";
|
||||
case RDMA_PS_TCP:
|
||||
return "TCP";
|
||||
case RDMA_PS_UDP:
|
||||
return "UDP";
|
||||
default:
|
||||
return "---";
|
||||
}
|
||||
}
|
||||
|
||||
static void print_cm_id_state(struct rd *rd, uint8_t state)
|
||||
{
|
||||
if (rd->json_output) {
|
||||
jsonw_string_field(rd->jw, "state", cm_id_state_to_str(state));
|
||||
return;
|
||||
}
|
||||
pr_out("state %s ", cm_id_state_to_str(state));
|
||||
}
|
||||
|
||||
static void print_ps(struct rd *rd, uint32_t ps)
|
||||
{
|
||||
if (rd->json_output) {
|
||||
jsonw_string_field(rd->jw, "ps", cm_id_ps_to_str(ps));
|
||||
return;
|
||||
}
|
||||
pr_out("ps %s ", cm_id_ps_to_str(ps));
|
||||
}
|
||||
|
||||
static void print_ipaddr(struct rd *rd, const char *key, char *addrstr,
|
||||
uint16_t port)
|
||||
{
|
||||
if (rd->json_output) {
|
||||
int name_size = INET6_ADDRSTRLEN + strlen(":65535");
|
||||
char json_name[name_size];
|
||||
|
||||
snprintf(json_name, name_size, "%s:%u", addrstr, port);
|
||||
jsonw_string_field(rd->jw, key, json_name);
|
||||
return;
|
||||
}
|
||||
pr_out("%s %s:%u ", key, addrstr, port);
|
||||
}
|
||||
|
||||
static int ss_ntop(struct nlattr *nla_line, char *addr_str, uint16_t *port)
|
||||
{
|
||||
struct __kernel_sockaddr_storage *addr;
|
||||
|
||||
addr = (struct __kernel_sockaddr_storage *)mnl_attr_get_payload(
|
||||
nla_line);
|
||||
switch (addr->ss_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)addr;
|
||||
|
||||
if (!inet_ntop(AF_INET, (const void *)&sin->sin_addr, addr_str,
|
||||
INET6_ADDRSTRLEN))
|
||||
return -EINVAL;
|
||||
*port = ntohs(sin->sin_port);
|
||||
break;
|
||||
}
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
|
||||
|
||||
if (!inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr,
|
||||
addr_str, INET6_ADDRSTRLEN))
|
||||
return -EINVAL;
|
||||
*port = ntohs(sin6->sin6_port);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int res_cm_id_line(struct rd *rd, const char *name, int idx,
|
||||
struct nlattr **nla_line)
|
||||
{
|
||||
char src_addr_str[INET6_ADDRSTRLEN];
|
||||
char dst_addr_str[INET6_ADDRSTRLEN];
|
||||
uint16_t src_port, dst_port;
|
||||
uint32_t port = 0, pid = 0;
|
||||
uint8_t type = 0, state;
|
||||
uint32_t lqpn = 0, ps;
|
||||
uint32_t cm_idn = 0;
|
||||
char *comm = NULL;
|
||||
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_STATE] ||
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_PS] ||
|
||||
(!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
|
||||
port = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]);
|
||||
|
||||
if (port && port != rd->port_idx)
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_LQPN])
|
||||
lqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
|
||||
|
||||
if (rd_is_filtered_attr(rd, "lqpn", lqpn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_LQPN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE])
|
||||
type = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_TYPE]);
|
||||
if (rd_is_string_filtered_attr(rd, "qp-type", qp_types_to_str(type),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_TYPE]))
|
||||
goto out;
|
||||
|
||||
ps = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PS]);
|
||||
if (rd_is_string_filtered_attr(rd, "ps", cm_id_ps_to_str(ps),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PS]))
|
||||
goto out;
|
||||
|
||||
state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_STATE]);
|
||||
if (rd_is_string_filtered_attr(rd, "state", cm_id_state_to_str(state),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_STATE]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR])
|
||||
if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR],
|
||||
src_addr_str, &src_port))
|
||||
goto out;
|
||||
if (rd_is_string_filtered_attr(rd, "src-addr", src_addr_str,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR]))
|
||||
goto out;
|
||||
if (rd_is_filtered_attr(rd, "src-port", src_port,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR])
|
||||
if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR],
|
||||
dst_addr_str, &dst_port))
|
||||
goto out;
|
||||
if (rd_is_string_filtered_attr(rd, "dst-addr", dst_addr_str,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]))
|
||||
goto out;
|
||||
if (rd_is_filtered_attr(rd, "dst-port", dst_port,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
|
||||
pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
comm = get_task_name(pid);
|
||||
}
|
||||
|
||||
if (rd_is_filtered_attr(rd, "pid", pid,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PID]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN])
|
||||
cm_idn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]);
|
||||
if (rd_is_filtered_attr(rd, "cm-idn", cm_idn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) {
|
||||
/* discard const from mnl_attr_get_str */
|
||||
comm = (char *)mnl_attr_get_str(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
|
||||
}
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_start_array(rd->jw);
|
||||
|
||||
print_link(rd, idx, name, port, nla_line);
|
||||
res_print_uint(rd, "cm-idn", cm_idn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]);
|
||||
res_print_uint(rd, "lqpn", lqpn, nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE])
|
||||
print_qp_type(rd, type);
|
||||
print_cm_id_state(rd, state);
|
||||
print_ps(rd, ps);
|
||||
res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
print_comm(rd, comm, nla_line);
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR])
|
||||
print_ipaddr(rd, "src-addr", src_addr_str, src_port);
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR])
|
||||
print_ipaddr(rd, "dst-addr", dst_addr_str, dst_port);
|
||||
|
||||
print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]);
|
||||
newline(rd);
|
||||
|
||||
out: if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
|
||||
free(comm);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
int res_cm_id_idx_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct rd *rd = data;
|
||||
const char *name;
|
||||
int idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
|
||||
return res_cm_id_line(rd, name, idx, tb);
|
||||
}
|
||||
|
||||
int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_table, *nla_entry;
|
||||
struct rd *rd = data;
|
||||
int ret = MNL_CB_OK;
|
||||
const char *name;
|
||||
int idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_RES_CM_ID])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
nla_table = tb[RDMA_NLDEV_ATTR_RES_CM_ID];
|
||||
|
||||
mnl_attr_for_each_nested(nla_entry, nla_table) {
|
||||
struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
||||
ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
|
||||
ret = res_cm_id_line(rd, name, idx, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* res-cq.c RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
#include "res.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
static const char *poll_ctx_to_str(uint8_t idx)
|
||||
{
|
||||
static const char * const cm_id_states_str[] = {
|
||||
"DIRECT", "SOFTIRQ", "WORKQUEUE", "UNBOUND_WORKQUEUE"};
|
||||
|
||||
if (idx < ARRAY_SIZE(cm_id_states_str))
|
||||
return cm_id_states_str[idx];
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static void print_poll_ctx(struct rd *rd, uint8_t poll_ctx, struct nlattr *attr)
|
||||
{
|
||||
if (!attr)
|
||||
return;
|
||||
|
||||
if (rd->json_output) {
|
||||
jsonw_string_field(rd->jw, "poll-ctx",
|
||||
poll_ctx_to_str(poll_ctx));
|
||||
return;
|
||||
}
|
||||
pr_out("poll-ctx %s ", poll_ctx_to_str(poll_ctx));
|
||||
}
|
||||
|
||||
static int res_cq_line(struct rd *rd, const char *name, int idx,
|
||||
struct nlattr **nla_line)
|
||||
{
|
||||
char *comm = NULL;
|
||||
uint32_t pid = 0;
|
||||
uint8_t poll_ctx = 0;
|
||||
uint32_t ctxn = 0;
|
||||
uint32_t cqn = 0;
|
||||
uint64_t users;
|
||||
uint32_t cqe;
|
||||
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_CQE] ||
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_USECNT] ||
|
||||
(!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
cqe = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CQE]);
|
||||
|
||||
users = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_USECNT]);
|
||||
if (rd_is_filtered_attr(rd, "users", users,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_USECNT]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX])
|
||||
poll_ctx =
|
||||
mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]);
|
||||
if (rd_is_string_filtered_attr(rd, "poll-ctx",
|
||||
poll_ctx_to_str(poll_ctx),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
|
||||
pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
comm = get_task_name(pid);
|
||||
}
|
||||
|
||||
if (rd_is_filtered_attr(rd, "pid", pid,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PID]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_CQN])
|
||||
cqn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CQN]);
|
||||
if (rd_is_filtered_attr(rd, "cqn", cqn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_CQN]))
|
||||
goto out;
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_CTXN])
|
||||
ctxn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CTXN]);
|
||||
if (rd_is_filtered_attr(rd, "ctxn", ctxn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_CTXN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
|
||||
/* discard const from mnl_attr_get_str */
|
||||
comm = (char *)mnl_attr_get_str(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_start_array(rd->jw);
|
||||
|
||||
print_dev(rd, idx, name);
|
||||
res_print_uint(rd, "cqn", cqn, nla_line[RDMA_NLDEV_ATTR_RES_CQN]);
|
||||
res_print_uint(rd, "cqe", cqe, nla_line[RDMA_NLDEV_ATTR_RES_CQE]);
|
||||
res_print_uint(rd, "users", users,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_USECNT]);
|
||||
print_poll_ctx(rd, poll_ctx, nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]);
|
||||
res_print_uint(rd, "ctxn", ctxn, nla_line[RDMA_NLDEV_ATTR_RES_CTXN]);
|
||||
res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
print_comm(rd, comm, nla_line);
|
||||
|
||||
print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]);
|
||||
newline(rd);
|
||||
|
||||
out: if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
|
||||
free(comm);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
int res_cq_idx_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct rd *rd = data;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
|
||||
return res_cq_line(rd, name, idx, tb);
|
||||
}
|
||||
|
||||
int res_cq_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_table, *nla_entry;
|
||||
struct rd *rd = data;
|
||||
int ret = MNL_CB_OK;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_RES_CQ])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
nla_table = tb[RDMA_NLDEV_ATTR_RES_CQ];
|
||||
|
||||
mnl_attr_for_each_nested(nla_entry, nla_table) {
|
||||
struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
||||
ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
|
||||
ret = res_cq_line(rd, name, idx, nla_line);
|
||||
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* res-mr.c RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
#include "res.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
static int res_mr_line(struct rd *rd, const char *name, int idx,
|
||||
struct nlattr **nla_line)
|
||||
{
|
||||
uint32_t rkey = 0, lkey = 0;
|
||||
uint64_t iova = 0, mrlen;
|
||||
char *comm = NULL;
|
||||
uint32_t pdn = 0;
|
||||
uint32_t mrn = 0;
|
||||
uint32_t pid = 0;
|
||||
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_MRLEN] ||
|
||||
(!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_RKEY])
|
||||
rkey = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RKEY]);
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_LKEY])
|
||||
lkey = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LKEY]);
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_IOVA])
|
||||
iova = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_IOVA]);
|
||||
|
||||
mrlen = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_MRLEN]);
|
||||
if (rd_is_filtered_attr(rd, "mrlen", mrlen,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_MRLEN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
|
||||
pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
comm = get_task_name(pid);
|
||||
}
|
||||
|
||||
if (rd_is_filtered_attr(rd, "pid", pid,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PID]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_MRN])
|
||||
mrn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_MRN]);
|
||||
if (rd_is_filtered_attr(rd, "mrn", mrn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_MRN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PDN])
|
||||
pdn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
if (rd_is_filtered_attr(rd, "pdn", pdn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PDN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
|
||||
/* discard const from mnl_attr_get_str */
|
||||
comm = (char *)mnl_attr_get_str(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_start_array(rd->jw);
|
||||
|
||||
print_dev(rd, idx, name);
|
||||
res_print_uint(rd, "mrn", mrn, nla_line[RDMA_NLDEV_ATTR_RES_MRN]);
|
||||
print_key(rd, "rkey", rkey, nla_line[RDMA_NLDEV_ATTR_RES_RKEY]);
|
||||
print_key(rd, "lkey", lkey, nla_line[RDMA_NLDEV_ATTR_RES_LKEY]);
|
||||
print_key(rd, "iova", iova, nla_line[RDMA_NLDEV_ATTR_RES_IOVA]);
|
||||
res_print_uint(rd, "mrlen", mrlen, nla_line[RDMA_NLDEV_ATTR_RES_MRLEN]);
|
||||
res_print_uint(rd, "pdn", pdn, nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
print_comm(rd, comm, nla_line);
|
||||
|
||||
print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]);
|
||||
newline(rd);
|
||||
|
||||
out:
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
|
||||
free(comm);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
int res_mr_idx_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct rd *rd = data;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
|
||||
return res_mr_line(rd, name, idx, tb);
|
||||
}
|
||||
|
||||
int res_mr_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_table, *nla_entry;
|
||||
struct rd *rd = data;
|
||||
int ret = MNL_CB_OK;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_RES_MR])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
nla_table = tb[RDMA_NLDEV_ATTR_RES_MR];
|
||||
|
||||
mnl_attr_for_each_nested(nla_entry, nla_table) {
|
||||
struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
||||
ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
|
||||
ret = res_mr_line(rd, name, idx, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* res-pd.c RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
#include "res.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
static int res_pd_line(struct rd *rd, const char *name, int idx,
|
||||
struct nlattr **nla_line)
|
||||
{
|
||||
uint32_t local_dma_lkey = 0, unsafe_global_rkey = 0;
|
||||
char *comm = NULL;
|
||||
uint32_t ctxn = 0;
|
||||
uint32_t pid = 0;
|
||||
uint32_t pdn = 0;
|
||||
uint64_t users;
|
||||
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_USECNT] ||
|
||||
(!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY])
|
||||
local_dma_lkey = mnl_attr_get_u32(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY]);
|
||||
|
||||
users = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_USECNT]);
|
||||
if (rd_is_filtered_attr(rd, "users", users,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_USECNT]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY])
|
||||
unsafe_global_rkey = mnl_attr_get_u32(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]);
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
|
||||
pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
comm = get_task_name(pid);
|
||||
}
|
||||
|
||||
if (rd_is_filtered_attr(rd, "pid", pid,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PID]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_CTXN])
|
||||
ctxn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CTXN]);
|
||||
|
||||
if (rd_is_filtered_attr(rd, "ctxn", ctxn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_CTXN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PDN])
|
||||
pdn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
if (rd_is_filtered_attr(rd, "pdn", pdn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PDN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
|
||||
/* discard const from mnl_attr_get_str */
|
||||
comm = (char *)mnl_attr_get_str(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_start_array(rd->jw);
|
||||
|
||||
print_dev(rd, idx, name);
|
||||
res_print_uint(rd, "pdn", pdn, nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
print_key(rd, "local_dma_lkey", local_dma_lkey,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY]);
|
||||
res_print_uint(rd, "users", users,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_USECNT]);
|
||||
print_key(rd, "unsafe_global_rkey", unsafe_global_rkey,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]);
|
||||
res_print_uint(rd, "ctxn", ctxn, nla_line[RDMA_NLDEV_ATTR_RES_CTXN]);
|
||||
res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
print_comm(rd, comm, nla_line);
|
||||
|
||||
print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]);
|
||||
newline(rd);
|
||||
|
||||
out: if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
|
||||
free(comm);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
int res_pd_idx_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct rd *rd = data;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
|
||||
return res_pd_line(rd, name, idx, tb);
|
||||
}
|
||||
|
||||
int res_pd_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_table, *nla_entry;
|
||||
struct rd *rd = data;
|
||||
int ret = MNL_CB_OK;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_RES_PD])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
nla_table = tb[RDMA_NLDEV_ATTR_RES_PD];
|
||||
|
||||
mnl_attr_for_each_nested(nla_entry, nla_table) {
|
||||
struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
||||
ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
|
||||
ret = res_pd_line(rd, name, idx, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* res-qp.c RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
#include "res.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
static const char *path_mig_to_str(uint8_t idx)
|
||||
{
|
||||
static const char *const path_mig_str[] = { "MIGRATED", "REARM",
|
||||
"ARMED" };
|
||||
|
||||
if (idx < ARRAY_SIZE(path_mig_str))
|
||||
return path_mig_str[idx];
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static const char *qp_states_to_str(uint8_t idx)
|
||||
{
|
||||
static const char *const qp_states_str[] = { "RESET", "INIT", "RTR",
|
||||
"RTS", "SQD", "SQE",
|
||||
"ERR" };
|
||||
|
||||
if (idx < ARRAY_SIZE(qp_states_str))
|
||||
return qp_states_str[idx];
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static void print_rqpn(struct rd *rd, uint32_t val, struct nlattr **nla_line)
|
||||
{
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_RQPN])
|
||||
return;
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_uint_field(rd->jw, "rqpn", val);
|
||||
else
|
||||
pr_out("rqpn %u ", val);
|
||||
}
|
||||
|
||||
static void print_type(struct rd *rd, uint32_t val)
|
||||
{
|
||||
if (rd->json_output)
|
||||
jsonw_string_field(rd->jw, "type", qp_types_to_str(val));
|
||||
else
|
||||
pr_out("type %s ", qp_types_to_str(val));
|
||||
}
|
||||
|
||||
static void print_state(struct rd *rd, uint32_t val)
|
||||
{
|
||||
if (rd->json_output)
|
||||
jsonw_string_field(rd->jw, "state", qp_states_to_str(val));
|
||||
else
|
||||
pr_out("state %s ", qp_states_to_str(val));
|
||||
}
|
||||
|
||||
static void print_rqpsn(struct rd *rd, uint32_t val, struct nlattr **nla_line)
|
||||
{
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN])
|
||||
return;
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_uint_field(rd->jw, "rq-psn", val);
|
||||
else
|
||||
pr_out("rq-psn %u ", val);
|
||||
}
|
||||
|
||||
static void print_pathmig(struct rd *rd, uint32_t val, struct nlattr **nla_line)
|
||||
{
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE])
|
||||
return;
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_string_field(rd->jw, "path-mig-state",
|
||||
path_mig_to_str(val));
|
||||
else
|
||||
pr_out("path-mig-state %s ", path_mig_to_str(val));
|
||||
}
|
||||
|
||||
static int res_qp_line(struct rd *rd, const char *name, int idx,
|
||||
struct nlattr **nla_line)
|
||||
{
|
||||
uint32_t lqpn, rqpn = 0, rq_psn = 0, sq_psn;
|
||||
uint8_t type, state, path_mig_state = 0;
|
||||
uint32_t port = 0, pid = 0;
|
||||
uint32_t pdn = 0;
|
||||
char *comm = NULL;
|
||||
|
||||
if (!nla_line[RDMA_NLDEV_ATTR_RES_LQPN] ||
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN] ||
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_TYPE] ||
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_STATE] ||
|
||||
(!nla_line[RDMA_NLDEV_ATTR_RES_PID] &&
|
||||
!nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) {
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
|
||||
port = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]);
|
||||
|
||||
if (port != rd->port_idx)
|
||||
goto out;
|
||||
|
||||
lqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
|
||||
if (rd_is_filtered_attr(rd, "lqpn", lqpn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_LQPN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PDN])
|
||||
pdn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
if (rd_is_filtered_attr(rd, "pdn", pdn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PDN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_RQPN])
|
||||
rqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RQPN]);
|
||||
if (rd_is_filtered_attr(rd, "rqpn", rqpn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_RQPN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN])
|
||||
rq_psn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN]);
|
||||
if (rd_is_filtered_attr(rd, "rq-psn", rq_psn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN]))
|
||||
goto out;
|
||||
|
||||
sq_psn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN]);
|
||||
if (rd_is_filtered_attr(rd, "sq-psn", sq_psn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE])
|
||||
path_mig_state = mnl_attr_get_u8(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE]);
|
||||
if (rd_is_string_filtered_attr(
|
||||
rd, "path-mig-state", path_mig_to_str(path_mig_state),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE]))
|
||||
goto out;
|
||||
|
||||
type = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_TYPE]);
|
||||
if (rd_is_string_filtered_attr(rd, "type", qp_types_to_str(type),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_TYPE]))
|
||||
goto out;
|
||||
|
||||
state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_STATE]);
|
||||
if (rd_is_string_filtered_attr(rd, "state", qp_states_to_str(state),
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_STATE]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
|
||||
pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
comm = get_task_name(pid);
|
||||
}
|
||||
|
||||
if (rd_is_filtered_attr(rd, "pid", pid,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_PID]))
|
||||
goto out;
|
||||
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
|
||||
/* discard const from mnl_attr_get_str */
|
||||
comm = (char *)mnl_attr_get_str(
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
|
||||
|
||||
if (rd->json_output)
|
||||
jsonw_start_array(rd->jw);
|
||||
|
||||
print_link(rd, idx, name, port, nla_line);
|
||||
|
||||
res_print_uint(rd, "lqpn", lqpn, nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
|
||||
print_rqpn(rd, rqpn, nla_line);
|
||||
|
||||
print_type(rd, type);
|
||||
print_state(rd, state);
|
||||
|
||||
print_rqpsn(rd, rq_psn, nla_line);
|
||||
res_print_uint(rd, "sq-psn", sq_psn,
|
||||
nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN]);
|
||||
|
||||
print_pathmig(rd, path_mig_state, nla_line);
|
||||
res_print_uint(rd, "pdn", pdn, nla_line[RDMA_NLDEV_ATTR_RES_PDN]);
|
||||
res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]);
|
||||
print_comm(rd, comm, nla_line);
|
||||
|
||||
print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]);
|
||||
newline(rd);
|
||||
out:
|
||||
if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
|
||||
free(comm);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
int res_qp_idx_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct rd *rd = data;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
|
||||
return res_qp_line(rd, name, idx, tb);
|
||||
}
|
||||
|
||||
int res_qp_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_table, *nla_entry;
|
||||
struct rd *rd = data;
|
||||
int ret = MNL_CB_OK;
|
||||
const char *name;
|
||||
uint32_t idx;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_RES_QP])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
|
||||
nla_table = tb[RDMA_NLDEV_ATTR_RES_QP];
|
||||
|
||||
mnl_attr_for_each_nested(nla_entry, nla_table) {
|
||||
struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
||||
ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
|
||||
ret = res_qp_line(rd, name, idx, nla_line);
|
||||
if (ret != MNL_CB_OK)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
940
rdma/res.c
940
rdma/res.c
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,148 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/*
|
||||
* res.h RDMA tool
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
#ifndef _RDMA_TOOL_RES_H_
|
||||
#define _RDMA_TOOL_RES_H_
|
||||
|
||||
#include "rdma.h"
|
||||
|
||||
int _res_send_msg(struct rd *rd, uint32_t command, mnl_cb_t callback);
|
||||
int _res_send_idx_msg(struct rd *rd, uint32_t command, mnl_cb_t callback,
|
||||
uint32_t idx, uint32_t id);
|
||||
|
||||
int res_pd_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_pd_idx_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_mr_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_mr_idx_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_cq_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_cq_idx_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_cm_id_idx_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_qp_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
int res_qp_idx_parse_cb(const struct nlmsghdr *nlh, void *data);
|
||||
|
||||
#define RES_FUNC(name, command, valid_filters, strict_port, id) \
|
||||
static inline int _##name(struct rd *rd) \
|
||||
{ \
|
||||
uint32_t idx; \
|
||||
int ret; \
|
||||
if (id) { \
|
||||
ret = rd_doit_index(rd, &idx); \
|
||||
if (ret) { \
|
||||
ret = _res_send_idx_msg(rd, command, \
|
||||
name##_idx_parse_cb, \
|
||||
idx, id); \
|
||||
if (!ret) \
|
||||
return ret; \
|
||||
/* Fallback for old systems without .doit callbacks */ \
|
||||
} \
|
||||
} \
|
||||
return _res_send_msg(rd, command, name##_parse_cb); \
|
||||
} \
|
||||
static inline int name(struct rd *rd) \
|
||||
{ \
|
||||
int ret = rd_build_filter(rd, valid_filters); \
|
||||
if (ret) \
|
||||
return ret; \
|
||||
if ((uintptr_t)valid_filters != (uintptr_t)NULL) { \
|
||||
ret = rd_set_arg_to_devname(rd); \
|
||||
if (ret) \
|
||||
return ret; \
|
||||
} \
|
||||
if (strict_port) \
|
||||
return rd_exec_dev(rd, _##name); \
|
||||
else \
|
||||
return rd_exec_link(rd, _##name, strict_port); \
|
||||
}
|
||||
|
||||
static const
|
||||
struct filters pd_valid_filters[MAX_NUMBER_OF_FILTERS] = {
|
||||
{ .name = "dev", .is_number = false },
|
||||
{ .name = "users", .is_number = true },
|
||||
{ .name = "pid", .is_number = true },
|
||||
{ .name = "ctxn", .is_number = true },
|
||||
{ .name = "pdn", .is_number = true, .is_doit = true },
|
||||
{ .name = "ctxn", .is_number = true }
|
||||
};
|
||||
|
||||
RES_FUNC(res_pd, RDMA_NLDEV_CMD_RES_PD_GET, pd_valid_filters, true,
|
||||
RDMA_NLDEV_ATTR_RES_PDN);
|
||||
|
||||
static const
|
||||
struct filters mr_valid_filters[MAX_NUMBER_OF_FILTERS] = {
|
||||
{ .name = "dev", .is_number = false },
|
||||
{ .name = "rkey", .is_number = true },
|
||||
{ .name = "lkey", .is_number = true },
|
||||
{ .name = "mrlen", .is_number = true },
|
||||
{ .name = "pid", .is_number = true },
|
||||
{ .name = "mrn", .is_number = true, .is_doit = true },
|
||||
{ .name = "pdn", .is_number = true }
|
||||
};
|
||||
|
||||
RES_FUNC(res_mr, RDMA_NLDEV_CMD_RES_MR_GET, mr_valid_filters, true,
|
||||
RDMA_NLDEV_ATTR_RES_MRN);
|
||||
|
||||
static const
|
||||
struct filters cq_valid_filters[MAX_NUMBER_OF_FILTERS] = {
|
||||
{ .name = "dev", .is_number = false },
|
||||
{ .name = "users", .is_number = true },
|
||||
{ .name = "poll-ctx", .is_number = false },
|
||||
{ .name = "pid", .is_number = true },
|
||||
{ .name = "cqn", .is_number = true, .is_doit = true },
|
||||
{ .name = "ctxn", .is_number = true }
|
||||
};
|
||||
|
||||
RES_FUNC(res_cq, RDMA_NLDEV_CMD_RES_CQ_GET, cq_valid_filters, true,
|
||||
RDMA_NLDEV_ATTR_RES_CQN);
|
||||
|
||||
static const
|
||||
struct filters cm_id_valid_filters[MAX_NUMBER_OF_FILTERS] = {
|
||||
{ .name = "link", .is_number = false },
|
||||
{ .name = "lqpn", .is_number = true },
|
||||
{ .name = "qp-type", .is_number = false },
|
||||
{ .name = "state", .is_number = false },
|
||||
{ .name = "ps", .is_number = false },
|
||||
{ .name = "dev-type", .is_number = false },
|
||||
{ .name = "transport-type", .is_number = false },
|
||||
{ .name = "pid", .is_number = true },
|
||||
{ .name = "src-addr", .is_number = false },
|
||||
{ .name = "src-port", .is_number = true },
|
||||
{ .name = "dst-addr", .is_number = false },
|
||||
{ .name = "dst-port", .is_number = true },
|
||||
{ .name = "cm-idn", .is_number = true, .is_doit = true }
|
||||
};
|
||||
|
||||
RES_FUNC(res_cm_id, RDMA_NLDEV_CMD_RES_CM_ID_GET, cm_id_valid_filters, false,
|
||||
RDMA_NLDEV_ATTR_RES_CM_IDN);
|
||||
|
||||
static const struct
|
||||
filters qp_valid_filters[MAX_NUMBER_OF_FILTERS] = {
|
||||
{ .name = "link", .is_number = false },
|
||||
{ .name = "lqpn", .is_number = true, .is_doit = true },
|
||||
{ .name = "rqpn", .is_number = true },
|
||||
{ .name = "pid", .is_number = true },
|
||||
{ .name = "sq-psn", .is_number = true },
|
||||
{ .name = "rq-psn", .is_number = true },
|
||||
{ .name = "type", .is_number = false },
|
||||
{ .name = "path-mig-state", .is_number = false },
|
||||
{ .name = "state", .is_number = false },
|
||||
{ .name = "pdn", .is_number = true },
|
||||
};
|
||||
|
||||
RES_FUNC(res_qp, RDMA_NLDEV_CMD_RES_QP_GET, qp_valid_filters, false,
|
||||
RDMA_NLDEV_ATTR_RES_LQPN);
|
||||
|
||||
char *get_task_name(uint32_t pid);
|
||||
void print_dev(struct rd *rd, uint32_t idx, const char *name);
|
||||
void print_link(struct rd *rd, uint32_t idx, const char *name, uint32_t port,
|
||||
struct nlattr **nla_line);
|
||||
void print_key(struct rd *rd, const char *name, uint64_t val,
|
||||
struct nlattr *nlattr);
|
||||
void res_print_uint(struct rd *rd, const char *name, uint64_t val,
|
||||
struct nlattr *nlattr);
|
||||
void print_comm(struct rd *rd, const char *str, struct nlattr **nla_line);
|
||||
const char *qp_types_to_str(uint8_t idx);
|
||||
|
||||
#endif /* _RDMA_TOOL_RES_H_ */
|
||||
87
rdma/utils.c
87
rdma/utils.c
|
|
@ -1,11 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* utils.c RDMA tool
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Leon Romanovsky <leonro@mellanox.com>
|
||||
*/
|
||||
|
||||
|
|
@ -126,6 +121,7 @@ static int add_filter(struct rd *rd, char *key, char *value,
|
|||
struct filter_entry *fe;
|
||||
bool key_found = false;
|
||||
int idx = 0;
|
||||
char *endp;
|
||||
int ret;
|
||||
|
||||
fe = calloc(1, sizeof(*fe));
|
||||
|
|
@ -168,6 +164,11 @@ static int add_filter(struct rd *rd, char *key, char *value,
|
|||
goto err_alloc;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
strtol(fe->value, &endp, 10);
|
||||
if (valid_filters[idx].is_doit && !errno && *endp == '\0')
|
||||
fe->is_doit = true;
|
||||
|
||||
for (idx = 0; idx < strlen(fe->value); idx++)
|
||||
fe->value[idx] = tolower(fe->value[idx]);
|
||||
|
||||
|
|
@ -182,6 +183,20 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool rd_doit_index(struct rd *rd, uint32_t *idx)
|
||||
{
|
||||
struct filter_entry *fe;
|
||||
|
||||
list_for_each_entry(fe, &rd->filter_list, list) {
|
||||
if (fe->is_doit) {
|
||||
*idx = atoi(fe->value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int rd_build_filter(struct rd *rd, const struct filters valid_filters[])
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -218,7 +233,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool rd_check_is_key_exist(struct rd *rd, const char *key)
|
||||
static bool rd_check_is_key_exist(struct rd *rd, const char *key)
|
||||
{
|
||||
struct filter_entry *fe;
|
||||
|
||||
|
|
@ -234,8 +249,8 @@ bool rd_check_is_key_exist(struct rd *rd, const char *key)
|
|||
* Check if string entry is filtered:
|
||||
* * key doesn't exist -> user didn't request -> not filtered
|
||||
*/
|
||||
bool rd_check_is_string_filtered(struct rd *rd,
|
||||
const char *key, const char *val)
|
||||
static bool rd_check_is_string_filtered(struct rd *rd, const char *key,
|
||||
const char *val)
|
||||
{
|
||||
bool key_is_filtered = false;
|
||||
struct filter_entry *fe;
|
||||
|
|
@ -285,7 +300,7 @@ out:
|
|||
* Check if key is filtered:
|
||||
* key doesn't exist -> user didn't request -> not filtered
|
||||
*/
|
||||
bool rd_check_is_filtered(struct rd *rd, const char *key, uint32_t val)
|
||||
static bool rd_check_is_filtered(struct rd *rd, const char *key, uint32_t val)
|
||||
{
|
||||
bool key_is_filtered = false;
|
||||
struct filter_entry *fe;
|
||||
|
|
@ -334,6 +349,24 @@ out:
|
|||
return key_is_filtered;
|
||||
}
|
||||
|
||||
bool rd_is_filtered_attr(struct rd *rd, const char *key, uint32_t val,
|
||||
struct nlattr *attr)
|
||||
{
|
||||
if (!attr)
|
||||
return rd_check_is_key_exist(rd, key);
|
||||
|
||||
return rd_check_is_filtered(rd, key, val);
|
||||
}
|
||||
|
||||
bool rd_is_string_filtered_attr(struct rd *rd, const char *key, const char *val,
|
||||
struct nlattr *attr)
|
||||
{
|
||||
if (!attr)
|
||||
rd_check_is_key_exist(rd, key);
|
||||
|
||||
return rd_check_is_string_filtered(rd, key, val);
|
||||
}
|
||||
|
||||
static void filters_cleanup(struct rd *rd)
|
||||
{
|
||||
struct filter_entry *fe, *tmp;
|
||||
|
|
@ -796,27 +829,37 @@ static int print_driver_entry(struct rd *rd, struct nlattr *key_attr,
|
|||
struct nlattr *val_attr,
|
||||
enum rdma_nldev_print_type print_type)
|
||||
{
|
||||
const char *key_str = mnl_attr_get_str(key_attr);
|
||||
int attr_type = nla_type(val_attr);
|
||||
int ret = -EINVAL;
|
||||
char *key_str;
|
||||
|
||||
if (asprintf(&key_str, "drv_%s", mnl_attr_get_str(key_attr)) == -1)
|
||||
return -ENOMEM;
|
||||
|
||||
switch (attr_type) {
|
||||
case RDMA_NLDEV_ATTR_DRIVER_STRING:
|
||||
return print_driver_string(rd, key_str,
|
||||
mnl_attr_get_str(val_attr));
|
||||
ret = print_driver_string(rd, key_str,
|
||||
mnl_attr_get_str(val_attr));
|
||||
break;
|
||||
case RDMA_NLDEV_ATTR_DRIVER_S32:
|
||||
return print_driver_s32(rd, key_str,
|
||||
mnl_attr_get_u32(val_attr), print_type);
|
||||
ret = print_driver_s32(rd, key_str, mnl_attr_get_u32(val_attr),
|
||||
print_type);
|
||||
break;
|
||||
case RDMA_NLDEV_ATTR_DRIVER_U32:
|
||||
return print_driver_u32(rd, key_str,
|
||||
mnl_attr_get_u32(val_attr), print_type);
|
||||
ret = print_driver_u32(rd, key_str, mnl_attr_get_u32(val_attr),
|
||||
print_type);
|
||||
break;
|
||||
case RDMA_NLDEV_ATTR_DRIVER_S64:
|
||||
return print_driver_s64(rd, key_str,
|
||||
mnl_attr_get_u64(val_attr), print_type);
|
||||
ret = print_driver_s64(rd, key_str, mnl_attr_get_u64(val_attr),
|
||||
print_type);
|
||||
break;
|
||||
case RDMA_NLDEV_ATTR_DRIVER_U64:
|
||||
return print_driver_u64(rd, key_str,
|
||||
mnl_attr_get_u64(val_attr), print_type);
|
||||
ret = print_driver_u64(rd, key_str, mnl_attr_get_u64(val_attr),
|
||||
print_type);
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
free(key_str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void print_driver_table(struct rd *rd, struct nlattr *tb)
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ static int bpf_print_opt(struct filter_util *qu, FILE *f,
|
|||
}
|
||||
|
||||
if (tb[TCA_BPF_OPS] && tb[TCA_BPF_OPS_LEN])
|
||||
bpf_print_ops(f, tb[TCA_BPF_OPS],
|
||||
bpf_print_ops(tb[TCA_BPF_OPS],
|
||||
rta_getattr_u16(tb[TCA_BPF_OPS_LEN]));
|
||||
|
||||
if (tb[TCA_BPF_ID])
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ static int matchall_print_opt(struct filter_util *qu, FILE *f,
|
|||
struct rtattr *opt, __u32 handle)
|
||||
{
|
||||
struct rtattr *tb[TCA_MATCHALL_MAX+1];
|
||||
struct tc_matchall_pcnt *pf = NULL;
|
||||
|
||||
if (opt == NULL)
|
||||
return 0;
|
||||
|
|
@ -143,6 +144,19 @@ static int matchall_print_opt(struct filter_util *qu, FILE *f,
|
|||
print_bool(PRINT_ANY, "not_in_hw", "\n not_in_hw", true);
|
||||
}
|
||||
|
||||
if (tb[TCA_MATCHALL_PCNT]) {
|
||||
if (RTA_PAYLOAD(tb[TCA_MATCHALL_PCNT]) < sizeof(*pf)) {
|
||||
print_string(PRINT_FP, NULL, "Broken perf counters\n", NULL);
|
||||
return -1;
|
||||
}
|
||||
pf = RTA_DATA(tb[TCA_MATCHALL_PCNT]);
|
||||
}
|
||||
|
||||
if (show_stats && NULL != pf)
|
||||
print_u64(PRINT_ANY, "rule_hit", " (rule hit %llu)",
|
||||
(unsigned long long) pf->rhit);
|
||||
|
||||
|
||||
if (tb[TCA_MATCHALL_ACT])
|
||||
tc_print_action(f, tb[TCA_MATCHALL_ACT], 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ tc_print_action(FILE *f, const struct rtattr *arg, unsigned short tot_acts)
|
|||
|
||||
parse_rtattr_nested(tb, tot_acts, arg);
|
||||
|
||||
if (tab_flush && NULL != tb[0] && NULL == tb[1])
|
||||
if (tab_flush && tb[0] && !tb[1])
|
||||
return tc_print_action_flush(f, tb[0]);
|
||||
|
||||
open_json_array(PRINT_JSON, "actions");
|
||||
|
|
|
|||
32
tc/m_bpf.c
32
tc/m_bpf.c
|
|
@ -157,7 +157,7 @@ static int bpf_print_opt(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
{
|
||||
struct rtattr *tb[TCA_ACT_BPF_MAX + 1];
|
||||
struct tc_act_bpf *parm;
|
||||
int dump_ok = 0;
|
||||
int d_ok = 0;
|
||||
|
||||
if (arg == NULL)
|
||||
return -1;
|
||||
|
|
@ -170,31 +170,33 @@ static int bpf_print_opt(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
}
|
||||
|
||||
parm = RTA_DATA(tb[TCA_ACT_BPF_PARMS]);
|
||||
fprintf(f, "bpf ");
|
||||
print_string(PRINT_ANY, "kind", "%s ", "bpf");
|
||||
|
||||
if (tb[TCA_ACT_BPF_NAME])
|
||||
fprintf(f, "%s ", rta_getattr_str(tb[TCA_ACT_BPF_NAME]));
|
||||
|
||||
print_string(PRINT_ANY, "bpf_name", "%s ",
|
||||
rta_getattr_str(tb[TCA_ACT_BPF_NAME]));
|
||||
if (tb[TCA_ACT_BPF_OPS] && tb[TCA_ACT_BPF_OPS_LEN]) {
|
||||
bpf_print_ops(f, tb[TCA_ACT_BPF_OPS],
|
||||
bpf_print_ops(tb[TCA_ACT_BPF_OPS],
|
||||
rta_getattr_u16(tb[TCA_ACT_BPF_OPS_LEN]));
|
||||
fprintf(f, " ");
|
||||
print_string(PRINT_FP, NULL, "%s", " ");
|
||||
}
|
||||
|
||||
if (tb[TCA_ACT_BPF_ID])
|
||||
dump_ok = bpf_dump_prog_info(f, rta_getattr_u32(tb[TCA_ACT_BPF_ID]));
|
||||
if (!dump_ok && tb[TCA_ACT_BPF_TAG]) {
|
||||
d_ok = bpf_dump_prog_info(f,
|
||||
rta_getattr_u32(tb[TCA_ACT_BPF_ID]));
|
||||
if (!d_ok && tb[TCA_ACT_BPF_TAG]) {
|
||||
SPRINT_BUF(b);
|
||||
|
||||
fprintf(f, "tag %s ",
|
||||
hexstring_n2a(RTA_DATA(tb[TCA_ACT_BPF_TAG]),
|
||||
RTA_PAYLOAD(tb[TCA_ACT_BPF_TAG]),
|
||||
b, sizeof(b)));
|
||||
print_string(PRINT_ANY, "tag", "tag %s ",
|
||||
hexstring_n2a(RTA_DATA(tb[TCA_ACT_BPF_TAG]),
|
||||
RTA_PAYLOAD(tb[TCA_ACT_BPF_TAG]),
|
||||
b, sizeof(b)));
|
||||
}
|
||||
|
||||
print_action_control(f, "default-action ", parm->action, "\n");
|
||||
fprintf(f, "\tindex %u ref %d bind %d", parm->index, parm->refcnt,
|
||||
parm->bindcnt);
|
||||
print_action_control(f, "default-action ", parm->action, _SL_);
|
||||
print_uint(PRINT_ANY, "index", "\t index %u", parm->index);
|
||||
print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
|
||||
print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
|
||||
|
||||
if (show_stats) {
|
||||
if (tb[TCA_ACT_BPF_TM]) {
|
||||
|
|
|
|||
|
|
@ -199,10 +199,11 @@ print_csum(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
uflag_1 = "?empty";
|
||||
}
|
||||
|
||||
print_string(PRINT_ANY, "kind", "%s ", "csum");
|
||||
snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s",
|
||||
uflag_1, uflag_2, uflag_3,
|
||||
uflag_4, uflag_5, uflag_6, uflag_7);
|
||||
print_string(PRINT_ANY, "csum", "csum (%s) ", buf);
|
||||
print_string(PRINT_ANY, "csum", "(%s) ", buf);
|
||||
|
||||
print_action_control(f, "action ", sel->action, "\n");
|
||||
print_uint(PRINT_ANY, "index", "\tindex %u", sel->index);
|
||||
|
|
|
|||
|
|
@ -299,9 +299,8 @@ static int parse_ipt(struct action_util *a, int *argc_p,
|
|||
int i;
|
||||
|
||||
for (i = 0; i < rargc; i++) {
|
||||
if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) {
|
||||
if (!argv[i] || strcmp(argv[i], "action") == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
iargc = argc = i;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,9 +224,8 @@ static int parse_ipt(struct action_util *a, int *argc_p,
|
|||
int i;
|
||||
|
||||
for (i = 0; i < rargc; i++) {
|
||||
if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) {
|
||||
if (!argv[i] || strcmp(argv[i], "action") == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
iargc = argc = i;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -859,7 +859,7 @@ void print_tcstats_attr(FILE *fp, struct rtattr *tb[], char *prefix, struct rtat
|
|||
|
||||
if (tb[TCA_STATS2]) {
|
||||
print_tcstats2_attr(fp, tb[TCA_STATS2], prefix, xstats);
|
||||
if (xstats && NULL == *xstats)
|
||||
if (xstats && !*xstats)
|
||||
goto compat_xstats;
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue