Commit 5d106e75 authored by GangCao's avatar GangCao Committed by Tomasz Zawadzki
Browse files

net: add the check for the add and delete IP operation

To properly return the error case when adding an existing
IP or delete a not existed IP. Proper test case is also
updated.

This is also to fix below issue:
https://github.com/spdk/spdk/issues/992



Change-Id: Ia4d3af8cc86d9bdb66b18a165510cd08f9bfa555
Signed-off-by: default avatarGangCao <gang.cao@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/476543


Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent a34d7d7b
Loading
Loading
Loading
Loading
+56 −10
Original line number Diff line number Diff line
@@ -304,20 +304,19 @@ exit:
	return ret;
}

static int spdk_interface_available(uint32_t ifc_index)
static struct spdk_interface *
spdk_interface_find_by_index(uint32_t ifc_index)
{
	struct spdk_interface *ifc_entry;

	pthread_mutex_lock(&interface_lock);
	/* Mutex must has benn held by the caller */
	TAILQ_FOREACH(ifc_entry, &g_interface_head, tailq) {
		if (ifc_entry->index == ifc_index) {
			pthread_mutex_unlock(&interface_lock);
			return 0;
			return ifc_entry;
		}
	}
	pthread_mutex_unlock(&interface_lock);

	return -1;
	return NULL;
}

static int netlink_addr_msg(uint32_t ifc_idx, uint32_t ip_address, uint32_t create)
@@ -335,10 +334,6 @@ static int netlink_addr_msg(uint32_t ifc_idx, uint32_t ip_address, uint32_t crea
	} req;
	struct rtattr *rta;

	if (spdk_interface_available(ifc_idx)) {
		return -ENODEV;
	}

	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	if (fd < 0) {
		SPDK_ERRLOG("socket failed!\n");
@@ -421,6 +416,43 @@ static void spdk_interface_ip_update(void)
	pthread_mutex_unlock(&interface_lock);
}

static int
spdk_interface_is_ip_address_in_use(int ifc_index, uint32_t addr, bool add)
{
	struct spdk_interface *ifc_entry;
	bool in_use = false;
	uint32_t idx = 0;

	spdk_interface_ip_update();

	pthread_mutex_lock(&interface_lock);
	ifc_entry = spdk_interface_find_by_index(ifc_index);
	if (ifc_entry == NULL) {
		pthread_mutex_unlock(&interface_lock);
		return -ENODEV;
	}

	for (idx = 0; idx < ifc_entry->num_ip_addresses; idx++) {
		if (ifc_entry->ip_address[idx] == addr) {
			in_use = true;
			break;
		}
	}
	pthread_mutex_unlock(&interface_lock);

	/* The IP address to add is alerady in use */
	if (add == true && in_use == true) {
		return -EADDRINUSE;
	}

	/* The IP address to delete is not in use */
	if (add == false && in_use == false) {
		return -ENXIO;
	}

	return 0;
}

int
spdk_interface_init(void)
{
@@ -451,8 +483,15 @@ int
spdk_interface_net_interface_add_ip_address(int ifc_index, char *ip_addr)
{
	uint32_t addr;
	int ret;

	addr = inet_addr(ip_addr);

	ret = spdk_interface_is_ip_address_in_use(ifc_index, addr, true);
	if (ret < 0) {
		return ret;
	}

	return netlink_addr_msg(ifc_index, addr, 1);
}

@@ -460,8 +499,15 @@ int
spdk_interface_net_interface_delete_ip_address(int ifc_index, char *ip_addr)
{
	uint32_t addr;
	int ret;

	addr = inet_addr(ip_addr);

	ret = spdk_interface_is_ip_address_in_use(ifc_index, addr, false);
	if (ret < 0) {
		return ret;
	}

	return netlink_addr_msg(ifc_index, addr, 0);
}

+8 −0
Original line number Diff line number Diff line
@@ -79,6 +79,10 @@ spdk_rpc_net_interface_add_ip_address(struct spdk_jsonrpc_request *request,
		if (ret_val == -ENODEV) {
			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_STATE,
							     "Interface %d not available", req.ifc_index);
		} else if (ret_val == -EADDRINUSE) {
			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
							     "IP address %s is already added to interface %d",
							     req.ip_address, req.ifc_index);
		} else {
			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
							 strerror(ret_val));
@@ -122,6 +126,10 @@ spdk_rpc_net_interface_delete_ip_address(struct spdk_jsonrpc_request *request,
		if (ret_val == -ENODEV) {
			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_STATE,
							     "Interface %d not available", req.ifc_index);
		} else if (ret_val == -ENXIO) {
			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
							     "IP address %s is not found in interface %d",
							     req.ip_address, req.ifc_index);
		} else {
			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
							 strerror(ret_val));
+38 −0
Original line number Diff line number Diff line
@@ -32,10 +32,47 @@ function rpc_config() {
	$rpc_py -s $1 bdev_malloc_create 64 512
}

function rpc_validate_ip() {
	# Always delete the IP first in case it is there already
	cmd="$rpc_py -s $1 net_interface_delete_ip_address 1 $MIGRATION_ADDRESS"
	if $cmd; then
		echo "Delete existing IP succeeded."
	else
		echo "Ignore the failure as IP did not exist."
	fi

	cmd="$rpc_py -s $1 net_interface_add_ip_address 1 $MIGRATION_ADDRESS"
	if $cmd; then
		echo "Add new IP succeeded."
	else
		echo "Add new IP failed. Expected to succeed..."
		exit 1;
	fi
	# Add same IP again
	if $cmd; then
		echo "Same IP existed. Expected to fail..."
		exit 1;
	fi

	cmd="$rpc_py -s $1 net_interface_delete_ip_address 1 $MIGRATION_ADDRESS"
	if $cmd; then
		echo "Delete existing IP succeeded."
	else
		echo "Delete existing IP failed. Expected to succeed..."
		exit 1;
	fi
	# Delete same IP again
	if $cmd; then
		echo "No required IP existed. Expected to fail..."
		exit 1;
	fi
}

function rpc_add_target_node() {
	$rpc_py -s $1 net_interface_add_ip_address 1 $MIGRATION_ADDRESS
	$rpc_py -s $1 iscsi_create_portal_group $PORTAL_TAG $MIGRATION_ADDRESS:$ISCSI_PORT
	$rpc_py -s $1 iscsi_create_target_node target1 target1_alias 'Malloc0:0' $PORTAL_TAG:$INITIATOR_TAG 64 -d
	$rpc_py -s $1 net_interface_delete_ip_address 1 $MIGRATION_ADDRESS
}

timing_enter ip_migration
@@ -66,6 +103,7 @@ for ((i = 0; i < 2; i++)); do
done

rpc_first_addr="/var/tmp/spdk0.sock"
rpc_validate_ip $rpc_first_addr
rpc_add_target_node $rpc_first_addr

sleep 1