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)
{
*/
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.
*/
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.
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) {