Current File : //proc/self/root/usr/src/linux-headers-6.8.0-60/tools/testing/selftests/net/mptcp/userspace_pm.sh
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0

# Double quotes to prevent globbing and word splitting is recommended in new
# code but we accept it.
#shellcheck disable=SC2086

# Some variables are used below but indirectly, see check_expected_one()
#shellcheck disable=SC2034

. "$(dirname "${0}")/mptcp_lib.sh"

mptcp_lib_check_mptcp
mptcp_lib_check_kallsyms

if ! mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
	echo "userspace pm tests are not supported by the kernel: SKIP"
	exit ${KSFT_SKIP}
fi

if ! ip -Version &> /dev/null; then
	echo "SKIP: Cannot not run test without ip tool"
	exit ${KSFT_SKIP}
fi

ANNOUNCED=${MPTCP_LIB_EVENT_ANNOUNCED}
REMOVED=${MPTCP_LIB_EVENT_REMOVED}
SUB_ESTABLISHED=${MPTCP_LIB_EVENT_SUB_ESTABLISHED}
SUB_CLOSED=${MPTCP_LIB_EVENT_SUB_CLOSED}
LISTENER_CREATED=${MPTCP_LIB_EVENT_LISTENER_CREATED}
LISTENER_CLOSED=${MPTCP_LIB_EVENT_LISTENER_CLOSED}

AF_INET=${MPTCP_LIB_AF_INET}
AF_INET6=${MPTCP_LIB_AF_INET6}

file=""
server_evts=""
client_evts=""
server_evts_pid=0
client_evts_pid=0
client4_pid=0
server4_pid=0
client6_pid=0
server6_pid=0
client4_token=""
server4_token=""
client6_token=""
server6_token=""
client4_port=0;
client6_port=0;
app4_port=50002
new4_port=50003
app6_port=50004
client_addr_id=${RANDOM:0:2}
server_addr_id=${RANDOM:0:2}

sec=$(date +%s)
rndh=$(printf %x "$sec")-$(mktemp -u XXXXXX)
ns1="ns1-$rndh"
ns2="ns2-$rndh"
ret=0
test_name=""

_printf() {
	stdbuf -o0 -e0 printf "${@}"
}

print_title()
{
	_printf "INFO: %s\n" "${1}"
}

# $1: test name
print_test()
{
	test_name="${1}"

	_printf "%-68s" "${test_name}"
}

print_results()
{
	_printf "[%s]\n" "${1}"
}

test_pass()
{
	print_results " OK "
	mptcp_lib_result_pass "${test_name}"
}

test_skip()
{
	print_results "SKIP"
	mptcp_lib_result_skip "${test_name}"
}

# $1: msg
test_fail()
{
	print_results "FAIL"
	ret=1

	if [ -n "${1}" ]; then
		_printf "\t%s\n" "${1}"
	fi

	mptcp_lib_result_fail "${test_name}"
}

# This function is used in the cleanup trap
#shellcheck disable=SC2317
cleanup()
{
	print_title "Cleanup"

	# Terminate the MPTCP connection and related processes
	local pid
	for pid in $client4_pid $server4_pid $client6_pid $server6_pid\
		   $server_evts_pid $client_evts_pid
	do
		mptcp_lib_kill_wait $pid
	done

	local netns
	for netns in "$ns1" "$ns2" ;do
		ip netns del "$netns"
	done

	rm -rf $file $client_evts $server_evts

	_printf "Done\n"
}

trap cleanup EXIT

# Create and configure network namespaces for testing
for i in "$ns1" "$ns2" ;do
	ip netns add "$i" || exit 1
	ip -net "$i" link set lo up
	ip netns exec "$i" sysctl -q net.mptcp.enabled=1
	ip netns exec "$i" sysctl -q net.mptcp.pm_type=1
done

#  "$ns1"              ns2
#     ns1eth2    ns2eth1

ip link add ns1eth2 netns "$ns1" type veth peer name ns2eth1 netns "$ns2"

# Add IPv4/v6 addresses to the namespaces
ip -net "$ns1" addr add 10.0.1.1/24 dev ns1eth2
ip -net "$ns1" addr add 10.0.2.1/24 dev ns1eth2
ip -net "$ns1" addr add dead:beef:1::1/64 dev ns1eth2 nodad
ip -net "$ns1" addr add dead:beef:2::1/64 dev ns1eth2 nodad
ip -net "$ns1" link set ns1eth2 up

ip -net "$ns2" addr add 10.0.1.2/24 dev ns2eth1
ip -net "$ns2" addr add 10.0.2.2/24 dev ns2eth1
ip -net "$ns2" addr add dead:beef:1::2/64 dev ns2eth1 nodad
ip -net "$ns2" addr add dead:beef:2::2/64 dev ns2eth1 nodad
ip -net "$ns2" link set ns2eth1 up

print_title "Init"
print_test "Created network namespaces ns1, ns2"
test_pass

make_connection()
{
	if [ -z "$file" ]; then
		file=$(mktemp)
	fi
	mptcp_lib_make_file "$file" 2 1

	local is_v6=$1
	local app_port=$app4_port
	local connect_addr="10.0.1.1"
	local client_addr="10.0.1.2"
	local listen_addr="0.0.0.0"
	if [ "$is_v6" = "v6" ]
	then
		connect_addr="dead:beef:1::1"
		client_addr="dead:beef:1::2"
		listen_addr="::"
		app_port=$app6_port
	else
		is_v6="v4"
	fi

	# Capture netlink events over the two network namespaces running
	# the MPTCP client and server
	if [ -z "$client_evts" ]; then
		client_evts=$(mktemp)
	fi
	mptcp_lib_events "${ns2}" "${client_evts}" client_evts_pid
	if [ -z "$server_evts" ]; then
		server_evts=$(mktemp)
	fi
	mptcp_lib_events "${ns1}" "${server_evts}" server_evts_pid
	sleep 0.5

	# Run the server
	ip netns exec "$ns1" \
	   ./mptcp_connect -s MPTCP -w 300 -p $app_port -l $listen_addr > /dev/null 2>&1 &
	local server_pid=$!
	sleep 0.5

	# Run the client, transfer $file and stay connected to the server
	# to conduct tests
	ip netns exec "$ns2" \
	   ./mptcp_connect -s MPTCP -w 300 -m sendfile -p $app_port $connect_addr\
	   2>&1 > /dev/null < "$file" &
	local client_pid=$!
	sleep 1

	# Capture client/server attributes from MPTCP connection netlink events

	local client_token
	local client_port
	local client_serverside
	local server_token
	local server_serverside

	client_token=$(mptcp_lib_evts_get_info token "$client_evts")
	client_port=$(mptcp_lib_evts_get_info sport "$client_evts")
	client_serverside=$(mptcp_lib_evts_get_info server_side "$client_evts")
	server_token=$(mptcp_lib_evts_get_info token "$server_evts")
	server_serverside=$(mptcp_lib_evts_get_info server_side "$server_evts")

	print_test "Established IP${is_v6} MPTCP Connection ns2 => ns1"
	if [ "$client_token" != "" ] && [ "$server_token" != "" ] && [ "$client_serverside" = 0 ] &&
		   [ "$server_serverside" = 1 ]
	then
		test_pass
		print_title "Connection info: ${client_addr}:${client_port} -> ${connect_addr}:${app_port}"
	else
		test_fail "Expected tokens (c:${client_token} - s:${server_token}) and server (c:${client_serverside} - s:${server_serverside})"
		mptcp_lib_result_print_all_tap
		exit 1
	fi

	if [ "$is_v6" = "v6" ]
	then
		client6_token=$client_token
		server6_token=$server_token
		client6_port=$client_port
		client6_pid=$client_pid
		server6_pid=$server_pid
	else
		client4_token=$client_token
		server4_token=$server_token
		client4_port=$client_port
		client4_pid=$client_pid
		server4_pid=$server_pid
	fi
}

# $1: var name ; $2: prev ret
check_expected_one()
{
	local var="${1}"
	local exp="e_${var}"
	local prev_ret="${2}"

	if [ "${!var}" = "${!exp}" ]
	then
		return 0
	fi

	if [ "${prev_ret}" = "0" ]
	then
		test_fail
	fi

	_printf "\tExpected value for '%s': '%s', got '%s'.\n" \
		"${var}" "${!exp}" "${!var}"
	return 1
}

# $@: all var names to check
check_expected()
{
	local rc=0
	local var

	for var in "${@}"
	do
		check_expected_one "${var}" "${rc}" || rc=1
	done

	if [ ${rc} -eq 0 ]
	then
		test_pass
		return 0
	fi

	return 1
}

verify_announce_event()
{
	local evt=$1
	local e_type=$2
	local e_token=$3
	local e_addr=$4
	local e_id=$5
	local e_dport=$6
	local e_af=$7
	local type
	local token
	local addr
	local dport
	local id

	type=$(mptcp_lib_evts_get_info type "$evt" $e_type)
	token=$(mptcp_lib_evts_get_info token "$evt" $e_type)
	if [ "$e_af" = "v6" ]
	then
		addr=$(mptcp_lib_evts_get_info daddr6 "$evt" $e_type)
	else
		addr=$(mptcp_lib_evts_get_info daddr4 "$evt" $e_type)
	fi
	dport=$(mptcp_lib_evts_get_info dport "$evt" $e_type)
	id=$(mptcp_lib_evts_get_info rem_id "$evt" $e_type)

	check_expected "type" "token" "addr" "dport" "id"
}

test_announce()
{
	print_title "Announce tests"

	# Capture events on the network namespace running the server
	:>"$server_evts"

	# ADD_ADDR using an invalid token should result in no action
	local invalid_token=$(( client4_token - 1))
	ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token $invalid_token id\
	   $client_addr_id dev ns2eth1 > /dev/null 2>&1

	local type
	type=$(mptcp_lib_evts_get_info type "$server_evts")
	print_test "ADD_ADDR 10.0.2.2 (ns2) => ns1, invalid token"
	if [ "$type" = "" ]
	then
		test_pass
	else
		test_fail "type defined: ${type}"
	fi

	# ADD_ADDR from the client to server machine reusing the subflow port
	:>"$server_evts"
	ip netns exec "$ns2"\
	   ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id $client_addr_id dev\
	   ns2eth1
	print_test "ADD_ADDR id:client 10.0.2.2 (ns2) => ns1, reuse port"
	sleep 0.5
	verify_announce_event $server_evts $ANNOUNCED $server4_token "10.0.2.2" $client_addr_id \
			      "$client4_port"

	# ADD_ADDR6 from the client to server machine reusing the subflow port
	:>"$server_evts"
	ip netns exec "$ns2" ./pm_nl_ctl ann\
	   dead:beef:2::2 token "$client6_token" id $client_addr_id dev ns2eth1
	print_test "ADD_ADDR6 id:client dead:beef:2::2 (ns2) => ns1, reuse port"
	sleep 0.5
	verify_announce_event "$server_evts" "$ANNOUNCED" "$server6_token" "dead:beef:2::2"\
			      "$client_addr_id" "$client6_port" "v6"

	# ADD_ADDR from the client to server machine using a new port
	:>"$server_evts"
	client_addr_id=$((client_addr_id+1))
	ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id\
	   $client_addr_id dev ns2eth1 port $new4_port
	print_test "ADD_ADDR id:client+1 10.0.2.2 (ns2) => ns1, new port"
	sleep 0.5
	verify_announce_event "$server_evts" "$ANNOUNCED" "$server4_token" "10.0.2.2"\
			      "$client_addr_id" "$new4_port"

	# Capture events on the network namespace running the client
	:>"$client_evts"

	# ADD_ADDR from the server to client machine reusing the subflow port
	ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
	   $server_addr_id dev ns1eth2
	print_test "ADD_ADDR id:server 10.0.2.1 (ns1) => ns2, reuse port"
	sleep 0.5
	verify_announce_event "$client_evts" "$ANNOUNCED" "$client4_token" "10.0.2.1"\
			      "$server_addr_id" "$app4_port"

	# ADD_ADDR6 from the server to client machine reusing the subflow port
	:>"$client_evts"
	ip netns exec "$ns1" ./pm_nl_ctl ann dead:beef:2::1 token "$server6_token" id\
	   $server_addr_id dev ns1eth2
	print_test "ADD_ADDR6 id:server dead:beef:2::1 (ns1) => ns2, reuse port"
	sleep 0.5
	verify_announce_event "$client_evts" "$ANNOUNCED" "$client6_token" "dead:beef:2::1"\
			      "$server_addr_id" "$app6_port" "v6"

	# ADD_ADDR from the server to client machine using a new port
	:>"$client_evts"
	server_addr_id=$((server_addr_id+1))
	ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
	   $server_addr_id dev ns1eth2 port $new4_port
	print_test "ADD_ADDR id:server+1 10.0.2.1 (ns1) => ns2, new port"
	sleep 0.5
	verify_announce_event "$client_evts" "$ANNOUNCED" "$client4_token" "10.0.2.1"\
			      "$server_addr_id" "$new4_port"
}

verify_remove_event()
{
	local evt=$1
	local e_type=$2
	local e_token=$3
	local e_id=$4
	local type
	local token
	local id

	type=$(mptcp_lib_evts_get_info type "$evt" $e_type)
	token=$(mptcp_lib_evts_get_info token "$evt" $e_type)
	id=$(mptcp_lib_evts_get_info rem_id "$evt" $e_type)

	check_expected "type" "token" "id"
}

test_remove()
{
	print_title "Remove tests"

	# Capture events on the network namespace running the server
	:>"$server_evts"

	# RM_ADDR using an invalid token should result in no action
	local invalid_token=$(( client4_token - 1 ))
	ip netns exec "$ns2" ./pm_nl_ctl rem token $invalid_token id\
	   $client_addr_id > /dev/null 2>&1
	print_test "RM_ADDR id:client ns2 => ns1, invalid token"
	local type
	type=$(mptcp_lib_evts_get_info type "$server_evts")
	if [ "$type" = "" ]
	then
		test_pass
	else
		test_fail
	fi

	# RM_ADDR using an invalid addr id should result in no action
	local invalid_id=$(( client_addr_id + 1 ))
	ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
	   $invalid_id > /dev/null 2>&1
	print_test "RM_ADDR id:client+1 ns2 => ns1, invalid id"
	type=$(mptcp_lib_evts_get_info type "$server_evts")
	if [ "$type" = "" ]
	then
		test_pass
	else
		test_fail
	fi

	# RM_ADDR from the client to server machine
	:>"$server_evts"
	ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
	   $client_addr_id
	print_test "RM_ADDR id:client ns2 => ns1"
	sleep 0.5
	verify_remove_event "$server_evts" "$REMOVED" "$server4_token" "$client_addr_id"

	# RM_ADDR from the client to server machine
	:>"$server_evts"
	client_addr_id=$(( client_addr_id - 1 ))
	ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
	   $client_addr_id
	print_test "RM_ADDR id:client-1 ns2 => ns1"
	sleep 0.5
	verify_remove_event "$server_evts" "$REMOVED" "$server4_token" "$client_addr_id"

	# RM_ADDR6 from the client to server machine
	:>"$server_evts"
	ip netns exec "$ns2" ./pm_nl_ctl rem token "$client6_token" id\
	   $client_addr_id
	print_test "RM_ADDR6 id:client-1 ns2 => ns1"
	sleep 0.5
	verify_remove_event "$server_evts" "$REMOVED" "$server6_token" "$client_addr_id"

	# Capture events on the network namespace running the client
	:>"$client_evts"

	# RM_ADDR from the server to client machine
	ip netns exec "$ns1" ./pm_nl_ctl rem token "$server4_token" id\
	   $server_addr_id
	print_test "RM_ADDR id:server ns1 => ns2"
	sleep 0.5
	verify_remove_event "$client_evts" "$REMOVED" "$client4_token" "$server_addr_id"

	# RM_ADDR from the server to client machine
	:>"$client_evts"
	server_addr_id=$(( server_addr_id - 1 ))
	ip netns exec "$ns1" ./pm_nl_ctl rem token "$server4_token" id\
	   $server_addr_id
	print_test "RM_ADDR id:server-1 ns1 => ns2"
	sleep 0.5
	verify_remove_event "$client_evts" "$REMOVED" "$client4_token" "$server_addr_id"

	# RM_ADDR6 from the server to client machine
	:>"$client_evts"
	ip netns exec "$ns1" ./pm_nl_ctl rem token "$server6_token" id\
	   $server_addr_id
	print_test "RM_ADDR6 id:server-1 ns1 => ns2"
	sleep 0.5
	verify_remove_event "$client_evts" "$REMOVED" "$client6_token" "$server_addr_id"
}

verify_subflow_events()
{
	local evt=$1
	local e_type=$2
	local e_token=$3
	local e_family=$4
	local e_saddr=$5
	local e_daddr=$6
	local e_dport=$7
	local e_locid=$8
	local e_remid=$9
	shift 2
	local e_from=$8
	local e_to=$9
	local type
	local token
	local family
	local saddr
	local daddr
	local dport
	local locid
	local remid
	local info
	local e_dport_txt

	# only display the fixed ports
	if [ "${e_dport}" -ge "${app4_port}" ] && [ "${e_dport}" -le "${app6_port}" ]; then
		e_dport_txt=":${e_dport}"
	fi

	info="${e_saddr} (${e_from}) => ${e_daddr}${e_dport_txt} (${e_to})"

	if [ "$e_type" = "$SUB_ESTABLISHED" ]
	then
		if [ "$e_family" = "$AF_INET6" ]
		then
			print_test "CREATE_SUBFLOW6 ${info}"
		else
			print_test "CREATE_SUBFLOW ${info}"
		fi
	else
		if [ "$e_family" = "$AF_INET6" ]
		then
			print_test "DESTROY_SUBFLOW6 ${info}"
		else
			print_test "DESTROY_SUBFLOW ${info}"
		fi
	fi

	type=$(mptcp_lib_evts_get_info type "$evt" $e_type)
	token=$(mptcp_lib_evts_get_info token "$evt" $e_type)
	family=$(mptcp_lib_evts_get_info family "$evt" $e_type)
	dport=$(mptcp_lib_evts_get_info dport "$evt" $e_type)
	locid=$(mptcp_lib_evts_get_info loc_id "$evt" $e_type)
	remid=$(mptcp_lib_evts_get_info rem_id "$evt" $e_type)
	if [ "$family" = "$AF_INET6" ]
	then
		saddr=$(mptcp_lib_evts_get_info saddr6 "$evt" $e_type)
		daddr=$(mptcp_lib_evts_get_info daddr6 "$evt" $e_type)
	else
		saddr=$(mptcp_lib_evts_get_info saddr4 "$evt" $e_type)
		daddr=$(mptcp_lib_evts_get_info daddr4 "$evt" $e_type)
	fi

	check_expected "type" "token" "daddr" "dport" "family" "saddr" "locid" "remid"
}

test_subflows()
{
	print_title "Subflows v4 or v6 only tests"

	# Capture events on the network namespace running the server
	:>"$server_evts"

	# Attempt to add a listener at 10.0.2.2:<subflow-port>
	ip netns exec "$ns2" ./pm_nl_ctl listen 10.0.2.2\
	   "$client4_port" &
	local listener_pid=$!

	# ADD_ADDR from client to server machine reusing the subflow port
	ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id\
	   $client_addr_id
	sleep 0.5

	# CREATE_SUBFLOW from server to client machine
	:>"$server_evts"
	ip netns exec "$ns1" ./pm_nl_ctl csf lip 10.0.2.1 lid 23 rip 10.0.2.2\
	   rport "$client4_port" token "$server4_token"
	sleep 0.5
	verify_subflow_events $server_evts $SUB_ESTABLISHED $server4_token $AF_INET "10.0.2.1" \
			      "10.0.2.2" "$client4_port" "23" "$client_addr_id" "ns1" "ns2"

	# Delete the listener from the client ns, if one was created
	mptcp_lib_kill_wait $listener_pid

	local sport
	sport=$(mptcp_lib_evts_get_info sport "$server_evts" $SUB_ESTABLISHED)

	# DESTROY_SUBFLOW from server to client machine
	:>"$server_evts"
	ip netns exec "$ns1" ./pm_nl_ctl dsf lip 10.0.2.1 lport "$sport" rip 10.0.2.2 rport\
	   "$client4_port" token "$server4_token"
	sleep 0.5
	verify_subflow_events "$server_evts" "$SUB_CLOSED" "$server4_token" "$AF_INET" "10.0.2.1"\
			      "10.0.2.2" "$client4_port" "23" "$client_addr_id" "ns1" "ns2"

	# RM_ADDR from client to server machine
	ip netns exec "$ns2" ./pm_nl_ctl rem id $client_addr_id token\
	   "$client4_token"
	sleep 0.5

	# Attempt to add a listener at dead:beef:2::2:<subflow-port>
	ip netns exec "$ns2" ./pm_nl_ctl listen dead:beef:2::2\
	   "$client6_port" &
	listener_pid=$!

	# ADD_ADDR6 from client to server machine reusing the subflow port
	:>"$server_evts"
	ip netns exec "$ns2" ./pm_nl_ctl ann dead:beef:2::2 token "$client6_token" id\
	   $client_addr_id
	sleep 0.5

	# CREATE_SUBFLOW6 from server to client machine
	:>"$server_evts"
	ip netns exec "$ns1" ./pm_nl_ctl csf lip dead:beef:2::1 lid 23 rip\
	   dead:beef:2::2 rport "$client6_port" token "$server6_token"
	sleep 0.5
	verify_subflow_events "$server_evts" "$SUB_ESTABLISHED" "$server6_token" "$AF_INET6"\
			      "dead:beef:2::1" "dead:beef:2::2" "$client6_port" "23"\
			      "$client_addr_id" "ns1" "ns2"

	# Delete the listener from the client ns, if one was created
	mptcp_lib_kill_wait $listener_pid

	sport=$(mptcp_lib_evts_get_info sport "$server_evts" $SUB_ESTABLISHED)

	# DESTROY_SUBFLOW6 from server to client machine
	:>"$server_evts"
	ip netns exec "$ns1" ./pm_nl_ctl dsf lip dead:beef:2::1 lport "$sport" rip\
	   dead:beef:2::2 rport "$client6_port" token "$server6_token"
	sleep 0.5
	verify_subflow_events "$server_evts" "$SUB_CLOSED" "$server6_token" "$AF_INET6"\
			      "dead:beef:2::1" "dead:beef:2::2" "$client6_port" "23"\
			      "$client_addr_id" "ns1" "ns2"

	# RM_ADDR from client to server machine
	ip netns exec "$ns2" ./pm_nl_ctl rem id $client_addr_id token\
	   "$client6_token"
	sleep 0.5

	# Attempt to add a listener at 10.0.2.2:<new-port>
	ip netns exec "$ns2" ./pm_nl_ctl listen 10.0.2.2\
	   $new4_port &
	listener_pid=$!

	# ADD_ADDR from client to server machine using a new port
	:>"$server_evts"
	ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id\
	   $client_addr_id port $new4_port
	sleep 0.5

	# CREATE_SUBFLOW from server to client machine
	:>"$server_evts"
	ip netns exec "$ns1" ./pm_nl_ctl csf lip 10.0.2.1 lid 23 rip 10.0.2.2 rport\
	   $new4_port token "$server4_token"
	sleep 0.5
	verify_subflow_events "$server_evts" "$SUB_ESTABLISHED" "$server4_token" "$AF_INET"\
			      "10.0.2.1" "10.0.2.2" "$new4_port" "23"\
			      "$client_addr_id" "ns1" "ns2"

	# Delete the listener from the client ns, if one was created
	mptcp_lib_kill_wait $listener_pid

	sport=$(mptcp_lib_evts_get_info sport "$server_evts" $SUB_ESTABLISHED)

	# DESTROY_SUBFLOW from server to client machine
	:>"$server_evts"
	ip netns exec "$ns1" ./pm_nl_ctl dsf lip 10.0.2.1 lport "$sport" rip 10.0.2.2 rport\
	   $new4_port token "$server4_token"
	sleep 0.5
	verify_subflow_events "$server_evts" "$SUB_CLOSED" "$server4_token" "$AF_INET" "10.0.2.1"\
			      "10.0.2.2" "$new4_port" "23" "$client_addr_id" "ns1" "ns2"

	# RM_ADDR from client to server machine
	ip netns exec "$ns2" ./pm_nl_ctl rem id $client_addr_id token\
	   "$client4_token"

	# Capture events on the network namespace running the client
	:>"$client_evts"

	# Attempt to add a listener at 10.0.2.1:<subflow-port>
	ip netns exec "$ns1" ./pm_nl_ctl listen 10.0.2.1\
	   $app4_port &
	listener_pid=$!

	# ADD_ADDR from server to client machine reusing the subflow port
	ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
	   $server_addr_id
	sleep 0.5

	# CREATE_SUBFLOW from client to server machine
	:>"$client_evts"
	ip netns exec "$ns2" ./pm_nl_ctl csf lip 10.0.2.2 lid 23 rip 10.0.2.1 rport\
	   $app4_port token "$client4_token"
	sleep 0.5
	verify_subflow_events $client_evts $SUB_ESTABLISHED $client4_token $AF_INET "10.0.2.2"\
			      "10.0.2.1" "$app4_port" "23" "$server_addr_id" "ns2" "ns1"

	# Delete the listener from the server ns, if one was created
	mptcp_lib_kill_wait $listener_pid

	sport=$(mptcp_lib_evts_get_info sport "$client_evts" $SUB_ESTABLISHED)

	# DESTROY_SUBFLOW from client to server machine
	:>"$client_evts"
	ip netns exec "$ns2" ./pm_nl_ctl dsf lip 10.0.2.2 lport "$sport" rip 10.0.2.1 rport\
	   $app4_port token "$client4_token"
	sleep 0.5
	verify_subflow_events "$client_evts" "$SUB_CLOSED" "$client4_token" "$AF_INET" "10.0.2.2"\
			      "10.0.2.1" "$app4_port" "23" "$server_addr_id" "ns2" "ns1"

	# RM_ADDR from server to client machine
	ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
	   "$server4_token"
	sleep 0.5

	# Attempt to add a listener at dead:beef:2::1:<subflow-port>
	ip netns exec "$ns1" ./pm_nl_ctl listen dead:beef:2::1\
	   $app6_port &
	listener_pid=$!

	# ADD_ADDR6 from server to client machine reusing the subflow port
	:>"$client_evts"
	ip netns exec "$ns1" ./pm_nl_ctl ann dead:beef:2::1 token "$server6_token" id\
	   $server_addr_id
	sleep 0.5

	# CREATE_SUBFLOW6 from client to server machine
	:>"$client_evts"
	ip netns exec "$ns2" ./pm_nl_ctl csf lip dead:beef:2::2 lid 23 rip\
	   dead:beef:2::1 rport $app6_port token "$client6_token"
	sleep 0.5
	verify_subflow_events "$client_evts" "$SUB_ESTABLISHED" "$client6_token"\
			      "$AF_INET6" "dead:beef:2::2"\
			      "dead:beef:2::1" "$app6_port" "23"\
			      "$server_addr_id" "ns2" "ns1"

	# Delete the listener from the server ns, if one was created
	mptcp_lib_kill_wait $listener_pid

	sport=$(mptcp_lib_evts_get_info sport "$client_evts" $SUB_ESTABLISHED)

	# DESTROY_SUBFLOW6 from client to server machine
	:>"$client_evts"
	ip netns exec "$ns2" ./pm_nl_ctl dsf lip dead:beef:2::2 lport "$sport" rip\
	   dead:beef:2::1 rport $app6_port token "$client6_token"
	sleep 0.5
	verify_subflow_events $client_evts $SUB_CLOSED $client6_token $AF_INET6 "dead:beef:2::2"\
			      "dead:beef:2::1" "$app6_port" "23" "$server_addr_id" "ns2" "ns1"

	# RM_ADDR6 from server to client machine
	ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
	   "$server6_token"
	sleep 0.5

	# Attempt to add a listener at 10.0.2.1:<new-port>
	ip netns exec "$ns1" ./pm_nl_ctl listen 10.0.2.1\
	   $new4_port &
	listener_pid=$!

	# ADD_ADDR from server to client machine using a new port
	:>"$client_evts"
	ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
	   $server_addr_id port $new4_port
	sleep 0.5

	# CREATE_SUBFLOW from client to server machine
	:>"$client_evts"
	ip netns exec "$ns2" ./pm_nl_ctl csf lip 10.0.2.2 lid 23 rip 10.0.2.1 rport\
	   $new4_port token "$client4_token"
	sleep 0.5
	verify_subflow_events "$client_evts" "$SUB_ESTABLISHED" "$client4_token" "$AF_INET"\
			      "10.0.2.2" "10.0.2.1" "$new4_port" "23" "$server_addr_id" "ns2" "ns1"

	# Delete the listener from the server ns, if one was created
	mptcp_lib_kill_wait $listener_pid

	sport=$(mptcp_lib_evts_get_info sport "$client_evts" $SUB_ESTABLISHED)

	# DESTROY_SUBFLOW from client to server machine
	:>"$client_evts"
	ip netns exec "$ns2" ./pm_nl_ctl dsf lip 10.0.2.2 lport "$sport" rip 10.0.2.1 rport\
	   $new4_port token "$client4_token"
	sleep 0.5
	verify_subflow_events "$client_evts" "$SUB_CLOSED" "$client4_token" "$AF_INET" "10.0.2.2"\
			      "10.0.2.1" "$new4_port" "23" "$server_addr_id" "ns2" "ns1"

	# RM_ADDR from server to client machine
	ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
	   "$server4_token"
}

test_subflows_v4_v6_mix()
{
	print_title "Subflows v4 and v6 mix tests"

	# Attempt to add a listener at 10.0.2.1:<subflow-port>
	ip netns exec "$ns1" ./pm_nl_ctl listen 10.0.2.1\
	   $app6_port &
	local listener_pid=$!

	# ADD_ADDR4 from server to client machine reusing the subflow port on
	# the established v6 connection
	:>"$client_evts"
	ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server6_token" id\
	   $server_addr_id dev ns1eth2
	print_test "ADD_ADDR4 id:server 10.0.2.1 (ns1) => ns2, reuse port"
	sleep 0.5
	verify_announce_event "$client_evts" "$ANNOUNCED" "$client6_token" "10.0.2.1"\
			      "$server_addr_id" "$app6_port"

	# CREATE_SUBFLOW from client to server machine
	:>"$client_evts"
	ip netns exec "$ns2" ./pm_nl_ctl csf lip 10.0.2.2 lid 23 rip 10.0.2.1 rport\
	   $app6_port token "$client6_token"
	sleep 0.5
	verify_subflow_events "$client_evts" "$SUB_ESTABLISHED" "$client6_token"\
			      "$AF_INET" "10.0.2.2" "10.0.2.1" "$app6_port" "23"\
			      "$server_addr_id" "ns2" "ns1"

	# Delete the listener from the server ns, if one was created
	mptcp_lib_kill_wait $listener_pid

	sport=$(mptcp_lib_evts_get_info sport "$client_evts" $SUB_ESTABLISHED)

	# DESTROY_SUBFLOW from client to server machine
	:>"$client_evts"
	ip netns exec "$ns2" ./pm_nl_ctl dsf lip 10.0.2.2 lport "$sport" rip 10.0.2.1 rport\
	   $app6_port token "$client6_token"
	sleep 0.5
	verify_subflow_events "$client_evts" "$SUB_CLOSED" "$client6_token" \
			      "$AF_INET" "10.0.2.2" "10.0.2.1" "$app6_port" "23"\
			      "$server_addr_id" "ns2" "ns1"

	# RM_ADDR from server to client machine
	ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
	   "$server6_token"
	sleep 0.5
}

test_prio()
{
	print_title "Prio tests"

	local count

	# Send MP_PRIO signal from client to server machine
	ip netns exec "$ns2" ./pm_nl_ctl set 10.0.1.2 port "$client4_port" flags backup token "$client4_token" rip 10.0.1.1 rport "$app4_port"
	sleep 0.5

	# Check TX
	print_test "MP_PRIO TX"
	count=$(mptcp_lib_get_counter "$ns2" "MPTcpExtMPPrioTx")
	if [ -z "$count" ]; then
		test_skip
	elif [ $count != 1 ]; then
		test_fail "Count != 1: ${count}"
	else
		test_pass
	fi

	# Check RX
	print_test "MP_PRIO RX"
	count=$(mptcp_lib_get_counter "$ns1" "MPTcpExtMPPrioRx")
	if [ -z "$count" ]; then
		test_skip
	elif [ $count != 1 ]; then
		test_fail "Count != 1: ${count}"
	else
		test_pass
	fi
}

verify_listener_events()
{
	local evt=$1
	local e_type=$2
	local e_family=$3
	local e_saddr=$4
	local e_sport=$5
	local type
	local family
	local saddr
	local sport

	type=$(mptcp_lib_evts_get_info type $evt $e_type)
	family=$(mptcp_lib_evts_get_info family $evt $e_type)
	sport=$(mptcp_lib_evts_get_info sport $evt $e_type)
	if [ $family ] && [ $family = $AF_INET6 ]; then
		saddr=$(mptcp_lib_evts_get_info saddr6 $evt $e_type)
	else
		saddr=$(mptcp_lib_evts_get_info saddr4 $evt $e_type)
	fi

	check_expected "type" "family" "saddr" "sport"
}

test_listener()
{
	print_title "Listener tests"

	if ! mptcp_lib_kallsyms_has "mptcp_event_pm_listener$"; then
		print_test "LISTENER events"
		test_skip
		return
	fi

	# Capture events on the network namespace running the client
	:>$client_evts

	# Attempt to add a listener at 10.0.2.2:<subflow-port>
	ip netns exec $ns2 ./pm_nl_ctl listen 10.0.2.2\
		$client4_port &
	local listener_pid=$!

	sleep 0.5
	print_test "CREATE_LISTENER 10.0.2.2 (client port)"
	verify_listener_events $client_evts $LISTENER_CREATED $AF_INET 10.0.2.2 $client4_port

	# ADD_ADDR from client to server machine reusing the subflow port
	ip netns exec $ns2 ./pm_nl_ctl ann 10.0.2.2 token $client4_token id\
		$client_addr_id
	sleep 0.5

	# CREATE_SUBFLOW from server to client machine
	ip netns exec $ns1 ./pm_nl_ctl csf lip 10.0.2.1 lid 23 rip 10.0.2.2\
		rport $client4_port token $server4_token
	sleep 0.5

	# Delete the listener from the client ns, if one was created
	mptcp_lib_kill_wait $listener_pid

	sleep 0.5
	print_test "CLOSE_LISTENER 10.0.2.2 (client port)"
	verify_listener_events $client_evts $LISTENER_CLOSED $AF_INET 10.0.2.2 $client4_port
}

print_title "Make connections"
make_connection
make_connection "v6"
print_title "Will be using address IDs ${client_addr_id} (client) and ${server_addr_id} (server)"

test_announce
test_remove
test_subflows
test_subflows_v4_v6_mix
test_prio
test_listener

mptcp_lib_result_print_all_tap
exit ${ret}
¿Qué es la limpieza dental de perros? - Clínica veterinaria


Es la eliminación del sarro y la placa adherida a la superficie de los dientes mediante un equipo de ultrasonidos que garantiza la integridad de las piezas dentales a la vez que elimina en profundidad cualquier resto de suciedad.

A continuación se procede al pulido de los dientes mediante una fresa especial que elimina la placa bacteriana y devuelve a los dientes el aspecto sano que deben tener.

Una vez terminado todo el proceso, se mantiene al perro en observación hasta que se despierta de la anestesia, bajo la atenta supervisión de un veterinario.

¿Cada cuánto tiempo tengo que hacerle una limpieza dental a mi perro?

A partir de cierta edad, los perros pueden necesitar una limpieza dental anual o bianual. Depende de cada caso. En líneas generales, puede decirse que los perros de razas pequeñas suelen acumular más sarro y suelen necesitar una atención mayor en cuanto a higiene dental.


Riesgos de una mala higiene


Los riesgos más evidentes de una mala higiene dental en los perros son los siguientes:

  • Cuando la acumulación de sarro no se trata, se puede producir una inflamación y retracción de las encías que puede descalzar el diente y provocar caídas.
  • Mal aliento (halitosis).
  • Sarro perros
  • Puede ir a más
  • Las bacterias de la placa pueden trasladarse a través del torrente circulatorio a órganos vitales como el corazón ocasionando problemas de endocarditis en las válvulas. Las bacterias pueden incluso acantonarse en huesos (La osteomielitis es la infección ósea, tanto cortical como medular) provocando mucho dolor y una artritis séptica).

¿Cómo se forma el sarro?

El sarro es la calcificación de la placa dental. Los restos de alimentos, junto con las bacterias presentes en la boca, van a formar la placa bacteriana o placa dental. Si la placa no se retira, al mezclarse con la saliva y los minerales presentes en ella, reaccionará formando una costra. La placa se calcifica y se forma el sarro.

El sarro, cuando se forma, es de color blanquecino pero a medida que pasa el tiempo se va poniendo amarillo y luego marrón.

Síntomas de una pobre higiene dental
La señal más obvia de una mala salud dental canina es el mal aliento.

Sin embargo, a veces no es tan fácil de detectar
Y hay perros que no se dejan abrir la boca por su dueño. Por ejemplo…

Recientemente nos trajeron a la clínica a un perro que parpadeaba de un ojo y decía su dueño que le picaba un lado de la cara. Tenía molestias y dificultad para comer, lo que había llevado a sus dueños a comprarle comida blanda (que suele ser un poco más cara y llevar más contenido en grasa) durante medio año. Después de una exploración oftalmológica, nos dimos cuenta de que el ojo tenía una úlcera en la córnea probablemente de rascarse . Además, el canto lateral del ojo estaba inflamado. Tenía lo que en humanos llamamos flemón pero como era un perro de pelo largo, no se le notaba a simple vista. Al abrirle la boca nos llamó la atención el ver una muela llena de sarro. Le realizamos una radiografía y encontramos una fístula que llegaba hasta la parte inferior del ojo.

Le tuvimos que extraer la muela. Tras esto, el ojo se curó completamente con unos colirios y una lentilla protectora de úlcera. Afortunadamente, la úlcera no profundizó y no perforó el ojo. Ahora el perro come perfectamente a pesar de haber perdido una muela.

¿Cómo mantener la higiene dental de tu perro?
Hay varias maneras de prevenir problemas derivados de la salud dental de tu perro.

Limpiezas de dientes en casa
Es recomendable limpiar los dientes de tu perro semanal o diariamente si se puede. Existe una gran variedad de productos que se pueden utilizar:

Pastas de dientes.
Cepillos de dientes o dedales para el dedo índice, que hacen más fácil la limpieza.
Colutorios para echar en agua de bebida o directamente sobre el diente en líquido o en spray.

En la Clínica Tus Veterinarios enseñamos a nuestros clientes a tomar el hábito de limpiar los dientes de sus perros desde que son cachorros. Esto responde a nuestro compromiso con la prevención de enfermedades caninas.

Hoy en día tenemos muchos clientes que limpian los dientes todos los días a su mascota, y como resultado, se ahorran el dinero de hacer limpiezas dentales profesionales y consiguen una mejor salud de su perro.


Limpiezas dentales profesionales de perros y gatos

Recomendamos hacer una limpieza dental especializada anualmente. La realizamos con un aparato de ultrasonidos que utiliza agua para quitar el sarro. Después, procedemos a pulir los dientes con un cepillo de alta velocidad y una pasta especial. Hacemos esto para proteger el esmalte.

La frecuencia de limpiezas dentales necesaria varía mucho entre razas. En general, las razas grandes tienen buena calidad de esmalte, por lo que no necesitan hacerlo tan a menudo e incluso pueden pasarse la vida sin requerir una limpieza. Sin embargo, razas pequeñas como el Yorkshire o el Maltés, deben hacérselas todos los años desde cachorros si se quiere conservar sus piezas dentales.

Otro factor fundamental es la calidad del pienso. Algunas marcas han diseñado croquetas que limpian la superficie del diente y de la muela al masticarse.

Ultrasonido para perros

¿Se necesita anestesia para las limpiezas dentales de perros y gatos?

La limpieza dental en perros no es una técnica que pueda practicarse sin anestesia general , aunque hay veces que los propietarios no quieren anestesiar y si tiene poco sarro y el perro es muy bueno se puede intentar…… , pero no se va a poder pulir ni acceder a todas la zona de la boca …. Además los limpiadores dentales van a irrigar agua y hay riesgo de aspiración a vías respiratorias si no se realiza una anestesia correcta con intubación traqueal . En resumen , sin anestesia no se va hacer una correcta limpieza dental.

Tampoco sirve la sedación ya que necesitamos que el animal esté totalmente quieto, y el veterinario tenga un acceso completo a todas sus piezas dentales y encías.

Alimentos para la limpieza dental

Hay que tener cierto cuidado a la hora de comprar determinados alimentos porque no todos son saludables. Algunos tienen demasiado contenido graso, que en exceso puede causar problemas cardiovasculares y obesidad.

Los mejores alimentos para los dientes son aquellos que están elaborados por empresas farmacéuticas y llevan componentes químicos con tratamientos específicos para el diente del perro. Esto implica no solo limpieza a través de la acción mecánica de morder sino también un tratamiento antibacteriano para prevenir el sarro.

Conclusión

Si eres como la mayoría de dueños, por falta de tiempo , es probable que no estés prestando la suficiente atención a la limpieza dental de tu perro. Por eso te animamos a que comiences a limpiar los dientes de tu perro y consideres atender a su higiene bucal con frecuencia.

Estas simples medidas pueden conllevar a que tu perro tenga una vida más larga y mucho más saludable.

Si te resulta imposible introducir un cepillo de dientes a tu perro en la boca, pásate con él por clínica Tus Veterinarios y te explicamos cómo hacerlo.

Necesitas hacer una limpieza dental profesional a tu mascota?
Llámanos al 622575274 o contacta con nosotros

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

¡Hola!