Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
tsn-measures
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
tsn-measures
Commits
d2ba96ee
Commit
d2ba96ee
authored
Jun 19, 2020
by
Joanne Hugé
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add older version of bpf_helpers.h
parent
a111675b
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
9 additions
and
242 deletions
+9
-242
packet-exchange/src/bpf_helpers.h
packet-exchange/src/bpf_helpers.h
+9
-242
No files found.
packet-exchange/src/bpf_helpers.h
View file @
d2ba96ee
/* SPDX-License-Identifier: GPL-2.0 */
/* Copied from $(LINUX)/tools/testing/selftests/bpf/bpf_helpers.h */
/* Added to fix compilation on old Ubuntu systems - please preserve when
updating file! */
#ifndef __always_inline
# define __always_inline inline __attribute__((always_inline))
#endif
#ifndef __BPF_HELPERS_H
#define __BPF_HELPERS_H
...
...
@@ -24,13 +15,6 @@ static int (*bpf_map_update_elem)(void *map, void *key, void *value,
(
void
*
)
BPF_FUNC_map_update_elem
;
static
int
(
*
bpf_map_delete_elem
)(
void
*
map
,
void
*
key
)
=
(
void
*
)
BPF_FUNC_map_delete_elem
;
static
int
(
*
bpf_map_push_elem
)(
void
*
map
,
void
*
value
,
unsigned
long
long
flags
)
=
(
void
*
)
BPF_FUNC_map_push_elem
;
static
int
(
*
bpf_map_pop_elem
)(
void
*
map
,
void
*
value
)
=
(
void
*
)
BPF_FUNC_map_pop_elem
;
static
int
(
*
bpf_map_peek_elem
)(
void
*
map
,
void
*
value
)
=
(
void
*
)
BPF_FUNC_map_peek_elem
;
static
int
(
*
bpf_probe_read
)(
void
*
dst
,
int
size
,
void
*
unsafe_ptr
)
=
(
void
*
)
BPF_FUNC_probe_read
;
static
unsigned
long
long
(
*
bpf_ktime_get_ns
)(
void
)
=
...
...
@@ -47,15 +31,12 @@ static unsigned long long (*bpf_get_current_uid_gid)(void) =
(
void
*
)
BPF_FUNC_get_current_uid_gid
;
static
int
(
*
bpf_get_current_comm
)(
void
*
buf
,
int
buf_size
)
=
(
void
*
)
BPF_FUNC_get_current_comm
;
static
unsigned
long
long
(
*
bpf_perf_event_read
)(
void
*
map
,
unsigned
long
long
flags
)
=
static
int
(
*
bpf_perf_event_read
)(
void
*
map
,
int
index
)
=
(
void
*
)
BPF_FUNC_perf_event_read
;
static
int
(
*
bpf_clone_redirect
)(
void
*
ctx
,
int
ifindex
,
int
flags
)
=
(
void
*
)
BPF_FUNC_clone_redirect
;
static
int
(
*
bpf_redirect
)(
int
ifindex
,
int
flags
)
=
(
void
*
)
BPF_FUNC_redirect
;
static
int
(
*
bpf_redirect_map
)(
void
*
map
,
int
key
,
int
flags
)
=
(
void
*
)
BPF_FUNC_redirect_map
;
static
int
(
*
bpf_perf_event_output
)(
void
*
ctx
,
void
*
map
,
unsigned
long
long
flags
,
void
*
data
,
int
size
)
=
...
...
@@ -78,120 +59,6 @@ static unsigned long long (*bpf_get_prandom_u32)(void) =
(
void
*
)
BPF_FUNC_get_prandom_u32
;
static
int
(
*
bpf_xdp_adjust_head
)(
void
*
ctx
,
int
offset
)
=
(
void
*
)
BPF_FUNC_xdp_adjust_head
;
static
int
(
*
bpf_xdp_adjust_meta
)(
void
*
ctx
,
int
offset
)
=
(
void
*
)
BPF_FUNC_xdp_adjust_meta
;
static
int
(
*
bpf_get_socket_cookie
)(
void
*
ctx
)
=
(
void
*
)
BPF_FUNC_get_socket_cookie
;
static
int
(
*
bpf_setsockopt
)(
void
*
ctx
,
int
level
,
int
optname
,
void
*
optval
,
int
optlen
)
=
(
void
*
)
BPF_FUNC_setsockopt
;
static
int
(
*
bpf_getsockopt
)(
void
*
ctx
,
int
level
,
int
optname
,
void
*
optval
,
int
optlen
)
=
(
void
*
)
BPF_FUNC_getsockopt
;
static
int
(
*
bpf_sock_ops_cb_flags_set
)(
void
*
ctx
,
int
flags
)
=
(
void
*
)
BPF_FUNC_sock_ops_cb_flags_set
;
static
int
(
*
bpf_sk_redirect_map
)(
void
*
ctx
,
void
*
map
,
int
key
,
int
flags
)
=
(
void
*
)
BPF_FUNC_sk_redirect_map
;
static
int
(
*
bpf_sk_redirect_hash
)(
void
*
ctx
,
void
*
map
,
void
*
key
,
int
flags
)
=
(
void
*
)
BPF_FUNC_sk_redirect_hash
;
static
int
(
*
bpf_sock_map_update
)(
void
*
map
,
void
*
key
,
void
*
value
,
unsigned
long
long
flags
)
=
(
void
*
)
BPF_FUNC_sock_map_update
;
static
int
(
*
bpf_sock_hash_update
)(
void
*
map
,
void
*
key
,
void
*
value
,
unsigned
long
long
flags
)
=
(
void
*
)
BPF_FUNC_sock_hash_update
;
static
int
(
*
bpf_perf_event_read_value
)(
void
*
map
,
unsigned
long
long
flags
,
void
*
buf
,
unsigned
int
buf_size
)
=
(
void
*
)
BPF_FUNC_perf_event_read_value
;
static
int
(
*
bpf_perf_prog_read_value
)(
void
*
ctx
,
void
*
buf
,
unsigned
int
buf_size
)
=
(
void
*
)
BPF_FUNC_perf_prog_read_value
;
static
int
(
*
bpf_override_return
)(
void
*
ctx
,
unsigned
long
rc
)
=
(
void
*
)
BPF_FUNC_override_return
;
static
int
(
*
bpf_msg_redirect_map
)(
void
*
ctx
,
void
*
map
,
int
key
,
int
flags
)
=
(
void
*
)
BPF_FUNC_msg_redirect_map
;
static
int
(
*
bpf_msg_redirect_hash
)(
void
*
ctx
,
void
*
map
,
void
*
key
,
int
flags
)
=
(
void
*
)
BPF_FUNC_msg_redirect_hash
;
static
int
(
*
bpf_msg_apply_bytes
)(
void
*
ctx
,
int
len
)
=
(
void
*
)
BPF_FUNC_msg_apply_bytes
;
static
int
(
*
bpf_msg_cork_bytes
)(
void
*
ctx
,
int
len
)
=
(
void
*
)
BPF_FUNC_msg_cork_bytes
;
static
int
(
*
bpf_msg_pull_data
)(
void
*
ctx
,
int
start
,
int
end
,
int
flags
)
=
(
void
*
)
BPF_FUNC_msg_pull_data
;
static
int
(
*
bpf_msg_push_data
)(
void
*
ctx
,
int
start
,
int
end
,
int
flags
)
=
(
void
*
)
BPF_FUNC_msg_push_data
;
static
int
(
*
bpf_msg_pop_data
)(
void
*
ctx
,
int
start
,
int
cut
,
int
flags
)
=
(
void
*
)
BPF_FUNC_msg_pop_data
;
static
int
(
*
bpf_bind
)(
void
*
ctx
,
void
*
addr
,
int
addr_len
)
=
(
void
*
)
BPF_FUNC_bind
;
static
int
(
*
bpf_xdp_adjust_tail
)(
void
*
ctx
,
int
offset
)
=
(
void
*
)
BPF_FUNC_xdp_adjust_tail
;
static
int
(
*
bpf_skb_get_xfrm_state
)(
void
*
ctx
,
int
index
,
void
*
state
,
int
size
,
int
flags
)
=
(
void
*
)
BPF_FUNC_skb_get_xfrm_state
;
static
int
(
*
bpf_sk_select_reuseport
)(
void
*
ctx
,
void
*
map
,
void
*
key
,
__u32
flags
)
=
(
void
*
)
BPF_FUNC_sk_select_reuseport
;
static
int
(
*
bpf_get_stack
)(
void
*
ctx
,
void
*
buf
,
int
size
,
int
flags
)
=
(
void
*
)
BPF_FUNC_get_stack
;
static
int
(
*
bpf_fib_lookup
)(
void
*
ctx
,
struct
bpf_fib_lookup
*
params
,
int
plen
,
__u32
flags
)
=
(
void
*
)
BPF_FUNC_fib_lookup
;
static
int
(
*
bpf_lwt_push_encap
)(
void
*
ctx
,
unsigned
int
type
,
void
*
hdr
,
unsigned
int
len
)
=
(
void
*
)
BPF_FUNC_lwt_push_encap
;
static
int
(
*
bpf_lwt_seg6_store_bytes
)(
void
*
ctx
,
unsigned
int
offset
,
void
*
from
,
unsigned
int
len
)
=
(
void
*
)
BPF_FUNC_lwt_seg6_store_bytes
;
static
int
(
*
bpf_lwt_seg6_action
)(
void
*
ctx
,
unsigned
int
action
,
void
*
param
,
unsigned
int
param_len
)
=
(
void
*
)
BPF_FUNC_lwt_seg6_action
;
static
int
(
*
bpf_lwt_seg6_adjust_srh
)(
void
*
ctx
,
unsigned
int
offset
,
unsigned
int
len
)
=
(
void
*
)
BPF_FUNC_lwt_seg6_adjust_srh
;
static
int
(
*
bpf_rc_repeat
)(
void
*
ctx
)
=
(
void
*
)
BPF_FUNC_rc_repeat
;
static
int
(
*
bpf_rc_keydown
)(
void
*
ctx
,
unsigned
int
protocol
,
unsigned
long
long
scancode
,
unsigned
int
toggle
)
=
(
void
*
)
BPF_FUNC_rc_keydown
;
static
unsigned
long
long
(
*
bpf_get_current_cgroup_id
)(
void
)
=
(
void
*
)
BPF_FUNC_get_current_cgroup_id
;
static
void
*
(
*
bpf_get_local_storage
)(
void
*
map
,
unsigned
long
long
flags
)
=
(
void
*
)
BPF_FUNC_get_local_storage
;
static
unsigned
long
long
(
*
bpf_skb_cgroup_id
)(
void
*
ctx
)
=
(
void
*
)
BPF_FUNC_skb_cgroup_id
;
static
unsigned
long
long
(
*
bpf_skb_ancestor_cgroup_id
)(
void
*
ctx
,
int
level
)
=
(
void
*
)
BPF_FUNC_skb_ancestor_cgroup_id
;
static
struct
bpf_sock
*
(
*
bpf_sk_lookup_tcp
)(
void
*
ctx
,
struct
bpf_sock_tuple
*
tuple
,
int
size
,
unsigned
long
long
netns_id
,
unsigned
long
long
flags
)
=
(
void
*
)
BPF_FUNC_sk_lookup_tcp
;
static
struct
bpf_sock
*
(
*
bpf_sk_lookup_udp
)(
void
*
ctx
,
struct
bpf_sock_tuple
*
tuple
,
int
size
,
unsigned
long
long
netns_id
,
unsigned
long
long
flags
)
=
(
void
*
)
BPF_FUNC_sk_lookup_udp
;
static
int
(
*
bpf_sk_release
)(
struct
bpf_sock
*
sk
)
=
(
void
*
)
BPF_FUNC_sk_release
;
static
int
(
*
bpf_skb_vlan_push
)(
void
*
ctx
,
__be16
vlan_proto
,
__u16
vlan_tci
)
=
(
void
*
)
BPF_FUNC_skb_vlan_push
;
static
int
(
*
bpf_skb_vlan_pop
)(
void
*
ctx
)
=
(
void
*
)
BPF_FUNC_skb_vlan_pop
;
static
int
(
*
bpf_rc_pointer_rel
)(
void
*
ctx
,
int
rel_x
,
int
rel_y
)
=
(
void
*
)
BPF_FUNC_rc_pointer_rel
;
static
void
(
*
bpf_spin_lock
)(
struct
bpf_spin_lock
*
lock
)
=
(
void
*
)
BPF_FUNC_spin_lock
;
static
void
(
*
bpf_spin_unlock
)(
struct
bpf_spin_lock
*
lock
)
=
(
void
*
)
BPF_FUNC_spin_unlock
;
static
struct
bpf_sock
*
(
*
bpf_sk_fullsock
)(
struct
bpf_sock
*
sk
)
=
(
void
*
)
BPF_FUNC_sk_fullsock
;
static
struct
bpf_tcp_sock
*
(
*
bpf_tcp_sock
)(
struct
bpf_sock
*
sk
)
=
(
void
*
)
BPF_FUNC_tcp_sock
;
static
struct
bpf_sock
*
(
*
bpf_get_listener_sock
)(
struct
bpf_sock
*
sk
)
=
(
void
*
)
BPF_FUNC_get_listener_sock
;
static
int
(
*
bpf_skb_ecn_set_ce
)(
void
*
ctx
)
=
(
void
*
)
BPF_FUNC_skb_ecn_set_ce
;
/* llvm builtin functions that eBPF C program may use to
* emit BPF_LD_ABS and BPF_LD_IND instructions
...
...
@@ -214,108 +81,22 @@ struct bpf_map_def {
unsigned
int
max_entries
;
unsigned
int
map_flags
;
unsigned
int
inner_map_idx
;
unsigned
int
numa_node
;
};
#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
struct ____btf_map_##name { \
type_key key; \
type_val value; \
}; \
struct ____btf_map_##name \
__attribute__ ((section(".maps." #name), used)) \
____btf_map_##name = { }
static
int
(
*
bpf_skb_load_bytes
)(
void
*
ctx
,
int
off
,
void
*
to
,
int
len
)
=
(
void
*
)
BPF_FUNC_skb_load_bytes
;
static
int
(
*
bpf_skb_load_bytes_relative
)(
void
*
ctx
,
int
off
,
void
*
to
,
int
len
,
__u32
start_header
)
=
(
void
*
)
BPF_FUNC_skb_load_bytes_relative
;
static
int
(
*
bpf_skb_store_bytes
)(
void
*
ctx
,
int
off
,
void
*
from
,
int
len
,
int
flags
)
=
(
void
*
)
BPF_FUNC_skb_store_bytes
;
static
int
(
*
bpf_l3_csum_replace
)(
void
*
ctx
,
int
off
,
int
from
,
int
to
,
int
flags
)
=
(
void
*
)
BPF_FUNC_l3_csum_replace
;
static
int
(
*
bpf_l4_csum_replace
)(
void
*
ctx
,
int
off
,
int
from
,
int
to
,
int
flags
)
=
(
void
*
)
BPF_FUNC_l4_csum_replace
;
static
int
(
*
bpf_csum_diff
)(
void
*
from
,
int
from_size
,
void
*
to
,
int
to_size
,
int
seed
)
=
(
void
*
)
BPF_FUNC_csum_diff
;
static
int
(
*
bpf_skb_under_cgroup
)(
void
*
ctx
,
void
*
map
,
int
index
)
=
(
void
*
)
BPF_FUNC_skb_under_cgroup
;
static
int
(
*
bpf_skb_change_head
)(
void
*
,
int
len
,
int
flags
)
=
(
void
*
)
BPF_FUNC_skb_change_head
;
static
int
(
*
bpf_skb_pull_data
)(
void
*
,
int
len
)
=
(
void
*
)
BPF_FUNC_skb_pull_data
;
static
unsigned
int
(
*
bpf_get_cgroup_classid
)(
void
*
ctx
)
=
(
void
*
)
BPF_FUNC_get_cgroup_classid
;
static
unsigned
int
(
*
bpf_get_route_realm
)(
void
*
ctx
)
=
(
void
*
)
BPF_FUNC_get_route_realm
;
static
int
(
*
bpf_skb_change_proto
)(
void
*
ctx
,
__be16
proto
,
__u64
flags
)
=
(
void
*
)
BPF_FUNC_skb_change_proto
;
static
int
(
*
bpf_skb_change_type
)(
void
*
ctx
,
__u32
type
)
=
(
void
*
)
BPF_FUNC_skb_change_type
;
static
unsigned
int
(
*
bpf_get_hash_recalc
)(
void
*
ctx
)
=
(
void
*
)
BPF_FUNC_get_hash_recalc
;
static
unsigned
long
long
(
*
bpf_get_current_task
)(
void
*
ctx
)
=
(
void
*
)
BPF_FUNC_get_current_task
;
static
int
(
*
bpf_skb_change_tail
)(
void
*
ctx
,
__u32
len
,
__u64
flags
)
=
(
void
*
)
BPF_FUNC_skb_change_tail
;
static
long
long
(
*
bpf_csum_update
)(
void
*
ctx
,
__u32
csum
)
=
(
void
*
)
BPF_FUNC_csum_update
;
static
void
(
*
bpf_set_hash_invalid
)(
void
*
ctx
)
=
(
void
*
)
BPF_FUNC_set_hash_invalid
;
static
int
(
*
bpf_get_numa_node_id
)(
void
)
=
(
void
*
)
BPF_FUNC_get_numa_node_id
;
static
int
(
*
bpf_probe_read_str
)(
void
*
ctx
,
__u32
size
,
const
void
*
unsafe_ptr
)
=
(
void
*
)
BPF_FUNC_probe_read_str
;
static
unsigned
int
(
*
bpf_get_socket_uid
)(
void
*
ctx
)
=
(
void
*
)
BPF_FUNC_get_socket_uid
;
static
unsigned
int
(
*
bpf_set_hash
)(
void
*
ctx
,
__u32
hash
)
=
(
void
*
)
BPF_FUNC_set_hash
;
static
int
(
*
bpf_skb_adjust_room
)(
void
*
ctx
,
__s32
len_diff
,
__u32
mode
,
unsigned
long
long
flags
)
=
(
void
*
)
BPF_FUNC_skb_adjust_room
;
/* Scan the ARCH passed in from ARCH env variable (see Makefile) */
#if defined(__TARGET_ARCH_x86)
#define bpf_target_x86
#define bpf_target_defined
#elif defined(__TARGET_ARCH_s930x)
#define bpf_target_s930x
#define bpf_target_defined
#elif defined(__TARGET_ARCH_arm64)
#define bpf_target_arm64
#define bpf_target_defined
#elif defined(__TARGET_ARCH_mips)
#define bpf_target_mips
#define bpf_target_defined
#elif defined(__TARGET_ARCH_powerpc)
#define bpf_target_powerpc
#define bpf_target_defined
#elif defined(__TARGET_ARCH_sparc)
#define bpf_target_sparc
#define bpf_target_defined
#else
#undef bpf_target_defined
#endif
/* Fall back to what the compiler says */
#ifndef bpf_target_defined
#if defined(__x86_64__)
#define bpf_target_x86
#elif defined(__s390x__)
#define bpf_target_s930x
#elif defined(__aarch64__)
#define bpf_target_arm64
#elif defined(__mips__)
#define bpf_target_mips
#elif defined(__powerpc__)
#define bpf_target_powerpc
#elif defined(__sparc__)
#define bpf_target_sparc
#endif
#endif
#if defined(bpf_target_x86)
#define PT_REGS_PARM1(x) ((x)->di)
#define PT_REGS_PARM2(x) ((x)->si)
...
...
@@ -328,7 +109,7 @@ static int (*bpf_skb_adjust_room)(void *ctx, __s32 len_diff, __u32 mode,
#define PT_REGS_SP(x) ((x)->sp)
#define PT_REGS_IP(x) ((x)->ip)
#elif defined(
bpf_target_s390x
)
#elif defined(
__s390x__
)
#define PT_REGS_PARM1(x) ((x)->gprs[2])
#define PT_REGS_PARM2(x) ((x)->gprs[3])
...
...
@@ -341,7 +122,7 @@ static int (*bpf_skb_adjust_room)(void *ctx, __s32 len_diff, __u32 mode,
#define PT_REGS_SP(x) ((x)->gprs[15])
#define PT_REGS_IP(x) ((x)->psw.addr)
#elif defined(
bpf_target_arm64
)
#elif defined(
__aarch64__
)
#define PT_REGS_PARM1(x) ((x)->regs[0])
#define PT_REGS_PARM2(x) ((x)->regs[1])
...
...
@@ -354,20 +135,7 @@ static int (*bpf_skb_adjust_room)(void *ctx, __s32 len_diff, __u32 mode,
#define PT_REGS_SP(x) ((x)->sp)
#define PT_REGS_IP(x) ((x)->pc)
#elif defined(bpf_target_mips)
#define PT_REGS_PARM1(x) ((x)->regs[4])
#define PT_REGS_PARM2(x) ((x)->regs[5])
#define PT_REGS_PARM3(x) ((x)->regs[6])
#define PT_REGS_PARM4(x) ((x)->regs[7])
#define PT_REGS_PARM5(x) ((x)->regs[8])
#define PT_REGS_RET(x) ((x)->regs[31])
#define PT_REGS_FP(x) ((x)->regs[30])
/* Works only with CONFIG_FRAME_POINTER */
#define PT_REGS_RC(x) ((x)->regs[1])
#define PT_REGS_SP(x) ((x)->regs[29])
#define PT_REGS_IP(x) ((x)->cp0_epc)
#elif defined(bpf_target_powerpc)
#elif defined(__powerpc__)
#define PT_REGS_PARM1(x) ((x)->gpr[3])
#define PT_REGS_PARM2(x) ((x)->gpr[4])
...
...
@@ -378,7 +146,7 @@ static int (*bpf_skb_adjust_room)(void *ctx, __s32 len_diff, __u32 mode,
#define PT_REGS_SP(x) ((x)->sp)
#define PT_REGS_IP(x) ((x)->nip)
#elif defined(
bpf_target_sparc
)
#elif defined(
__sparc__
)
#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0])
#define PT_REGS_PARM2(x) ((x)->u_regs[UREG_I1])
...
...
@@ -388,8 +156,6 @@ static int (*bpf_skb_adjust_room)(void *ctx, __s32 len_diff, __u32 mode,
#define PT_REGS_RET(x) ((x)->u_regs[UREG_I7])
#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0])
#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP])
/* Should this also be a bpf_target check for the sparc case? */
#if defined(__arch64__)
#define PT_REGS_IP(x) ((x)->tpc)
#else
...
...
@@ -398,10 +164,10 @@ static int (*bpf_skb_adjust_room)(void *ctx, __s32 len_diff, __u32 mode,
#endif
#ifdef
bpf_target_powerpc
#ifdef
__powerpc__
#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; })
#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
#elif
bpf_target_sparc
#elif
defined(__sparc__)
#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); })
#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP
#else
...
...
@@ -412,4 +178,5 @@ static int (*bpf_skb_adjust_room)(void *ctx, __s32 len_diff, __u32 mode,
(void *)(PT_REGS_FP(ctx) + sizeof(ip))); })
#endif
#
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment