kni: add function to set link state on kernel interface
Add a new API function to KNI, rte_kni_update_link() to allow DPDK applications to update the link status for KNI network interfaces in the linux kernel. Signed-off-by: Dan Gora <dg@adax.com> Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
parent
fd5f33323e
commit
c6fd54f28c
@ -717,6 +717,47 @@ rte_kni_unregister_handlers(struct rte_kni *kni)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __rte_experimental
|
||||
rte_kni_update_link(struct rte_kni *kni, unsigned int linkup)
|
||||
{
|
||||
char path[64];
|
||||
char old_carrier[2];
|
||||
const char *new_carrier;
|
||||
int old_linkup;
|
||||
int fd, ret;
|
||||
|
||||
if (kni == NULL)
|
||||
return -1;
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/devices/virtual/net/%s/carrier",
|
||||
kni->name);
|
||||
|
||||
fd = open(path, O_RDWR);
|
||||
if (fd == -1) {
|
||||
RTE_LOG(ERR, KNI, "Failed to open file: %s.\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = read(fd, old_carrier, 2);
|
||||
if (ret < 1) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
old_linkup = (old_carrier[0] == '1');
|
||||
|
||||
new_carrier = linkup ? "1" : "0";
|
||||
ret = write(fd, new_carrier, 1);
|
||||
if (ret < 1) {
|
||||
RTE_LOG(ERR, KNI, "Failed to write file: %s.\n", path);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return old_linkup;
|
||||
}
|
||||
|
||||
void
|
||||
rte_kni_close(void)
|
||||
{
|
||||
|
@ -232,6 +232,26 @@ int rte_kni_register_handlers(struct rte_kni *kni, struct rte_kni_ops *ops);
|
||||
*/
|
||||
int rte_kni_unregister_handlers(struct rte_kni *kni);
|
||||
|
||||
/**
|
||||
* Update link carrier state for KNI port.
|
||||
*
|
||||
* Update the linkup/linkdown state of a KNI interface in the kernel.
|
||||
*
|
||||
* @param kni
|
||||
* pointer to struct rte_kni.
|
||||
* @param linkup
|
||||
* New link state:
|
||||
* 0 for linkdown.
|
||||
* > 0 for linkup.
|
||||
*
|
||||
* @return
|
||||
* On failure: -1
|
||||
* Previous link state == linkdown: 0
|
||||
* Previous link state == linkup: 1
|
||||
*/
|
||||
int __rte_experimental
|
||||
rte_kni_update_link(struct rte_kni *kni, unsigned int linkup);
|
||||
|
||||
/**
|
||||
* Close KNI device.
|
||||
*/
|
||||
|
@ -15,3 +15,9 @@ DPDK_2.0 {
|
||||
|
||||
local: *;
|
||||
};
|
||||
|
||||
EXPERIMENTAL {
|
||||
global:
|
||||
|
||||
rte_kni_update_link;
|
||||
};
|
||||
|
@ -118,6 +118,79 @@ kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
|
||||
port_id, kni_pkt_mtu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
test_kni_link_change(void)
|
||||
{
|
||||
int ret;
|
||||
int pid;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
printf("Error: Failed to fork a process\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
printf("Starting KNI Link status change tests.\n");
|
||||
if (system(IFCONFIG TEST_KNI_PORT" up") == -1) {
|
||||
ret = -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = rte_kni_update_link(test_kni_ctx, 1);
|
||||
if (ret < 0) {
|
||||
printf("Failed to change link state to Up ret=%d.\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
rte_delay_ms(1000);
|
||||
printf("KNI: Set LINKUP, previous state=%d\n", ret);
|
||||
|
||||
ret = rte_kni_update_link(test_kni_ctx, 0);
|
||||
if (ret != 1) {
|
||||
printf(
|
||||
"Failed! Previous link state should be 1, returned %d.\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
rte_delay_ms(1000);
|
||||
printf("KNI: Set LINKDOWN, previous state=%d\n", ret);
|
||||
|
||||
ret = rte_kni_update_link(test_kni_ctx, 1);
|
||||
if (ret != 0) {
|
||||
printf(
|
||||
"Failed! Previous link state should be 0, returned %d.\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
printf("KNI: Set LINKUP, previous state=%d\n", ret);
|
||||
|
||||
ret = 0;
|
||||
rte_delay_ms(1000);
|
||||
|
||||
error:
|
||||
if (system(IFCONFIG TEST_KNI_PORT" down") == -1)
|
||||
ret = -1;
|
||||
|
||||
printf("KNI: Link status change tests: %s.\n",
|
||||
(ret == 0) ? "Passed" : "Failed");
|
||||
exit(ret);
|
||||
} else {
|
||||
int p_ret, status;
|
||||
|
||||
while (1) {
|
||||
p_ret = waitpid(pid, &status, WNOHANG);
|
||||
if (p_ret != 0) {
|
||||
if (WIFEXITED(status))
|
||||
return WEXITSTATUS(status);
|
||||
return -1;
|
||||
}
|
||||
rte_delay_ms(10);
|
||||
rte_kni_handle_request(test_kni_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This loop fully tests the basic functions of KNI. e.g. transmitting,
|
||||
* receiving to, from kernel space, and kernel requests.
|
||||
@ -401,6 +474,10 @@ test_kni_processing(uint16_t port_id, struct rte_mempool *mp)
|
||||
goto fail_kni;
|
||||
}
|
||||
|
||||
ret = test_kni_link_change();
|
||||
if (ret != 0)
|
||||
goto fail_kni;
|
||||
|
||||
rte_eal_mp_remote_launch(test_kni_loop, NULL, CALL_MASTER);
|
||||
RTE_LCORE_FOREACH_SLAVE(i) {
|
||||
if (rte_eal_wait_lcore(i) < 0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user