[v4,1/6] kni: add API to set link status on kernel interface

Message ID 20181017010412.23141-2-dg@adax.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series [v4,1/6] kni: add API to set link status on kernel interface |

Checks

Context Check Description
ci/Intel-compilation success Compilation OK
ci/checkpatch warning coding style issues

Commit Message

Dan Gora Oct. 17, 2018, 1:04 a.m. UTC
  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>
---
 lib/librte_kni/rte_kni.c           | 41 ++++++++++++++++++++++++++++++
 lib/librte_kni/rte_kni.h           | 20 +++++++++++++++
 lib/librte_kni/rte_kni_version.map |  6 +++++
 3 files changed, 67 insertions(+)
  

Comments

Ferruh Yigit Oct. 18, 2018, 1:44 p.m. UTC | #1
On 10/17/2018 2:04 AM, Dan Gora wrote:
> 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>
> ---
>  lib/librte_kni/rte_kni.c           | 41 ++++++++++++++++++++++++++++++
>  lib/librte_kni/rte_kni.h           | 20 +++++++++++++++
>  lib/librte_kni/rte_kni_version.map |  6 +++++
>  3 files changed, 67 insertions(+)
> 
> diff --git a/lib/librte_kni/rte_kni.c b/lib/librte_kni/rte_kni.c
> index b8edd40f4..c9726d4f8 100644
> --- a/lib/librte_kni/rte_kni.c
> +++ b/lib/librte_kni/rte_kni.c
> @@ -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);

KNI sample application calls this API each 100ms, so this keeps writing
"carrier" file.

What do you think writing to "carrier" file only if status changed?

And it is possible to register to RTE_ETH_EVENT_INTR_LSC event in sample
application instead of polling but not sure if all drivers supports it.

Or what do you think storing the link status in sample application and call this
function only if link status changed?
  
Dan Gora Oct. 18, 2018, 7 p.m. UTC | #2
On Thu, Oct 18, 2018 at 10:44 AM Ferruh Yigit <ferruh.yigit@intel.com> wrote:
>
> KNI sample application calls this API each 100ms, so this keeps writing
> "carrier" file.
>
> What do you think writing to "carrier" file only if status changed?
>
> And it is possible to register to RTE_ETH_EVENT_INTR_LSC event in sample
> application instead of polling but not sure if all drivers supports it.

Yeah I'm not really interested in implementing this to be honest.  I
really don't have time.

> Or what do you think storing the link status in sample application and call this
> function only if link status changed?

No, one of the major points of this API was to NOT have to carry
around this state in the application.

d
  

Patch

diff --git a/lib/librte_kni/rte_kni.c b/lib/librte_kni/rte_kni.c
index b8edd40f4..c9726d4f8 100644
--- a/lib/librte_kni/rte_kni.c
+++ b/lib/librte_kni/rte_kni.c
@@ -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)
 {
diff --git a/lib/librte_kni/rte_kni.h b/lib/librte_kni/rte_kni.h
index 601abdfc6..02ca43b4b 100644
--- a/lib/librte_kni/rte_kni.h
+++ b/lib/librte_kni/rte_kni.h
@@ -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.
  */
diff --git a/lib/librte_kni/rte_kni_version.map b/lib/librte_kni/rte_kni_version.map
index acd515eb0..c877dc6aa 100644
--- a/lib/librte_kni/rte_kni_version.map
+++ b/lib/librte_kni/rte_kni_version.map
@@ -15,3 +15,9 @@  DPDK_2.0 {
 
 	local: *;
 };
+
+EXPERIMENTAL {
+	global:
+
+	rte_kni_update_link;
+};