aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Uvarov <maxim.uvarov@linaro.org>2015-06-08 10:07:22 +0300
committerZoltan Kiss <zoltan.kiss@linaro.org>2015-06-09 19:34:50 +0100
commit19121fd26494c136b3ec5734dccd26abc0751335 (patch)
treeb0c1a106c2b3ca8a35f2e714e6eb138efa6ac640
parent3000df7d88b57af6ed2c1c2b383e1966818d556f (diff)
dpdk: pktio implement promisc mode on vdevs
DPDK PMD vdev like pcap does not support switching promisc mode. Use system calls for corresponding devices. Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org> Signed-off-by: Zoltan Kiss <zoltan.kiss@linaro.org>
-rw-r--r--platform/linux-dpdk/include/odp_packet_dpdk.h2
-rw-r--r--platform/linux-dpdk/odp_packet_dpdk.c5
-rw-r--r--platform/linux-dpdk/odp_packet_io.c87
3 files changed, 91 insertions, 3 deletions
diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h b/platform/linux-dpdk/include/odp_packet_dpdk.h
index ced4f5b63..608e4799b 100644
--- a/platform/linux-dpdk/include/odp_packet_dpdk.h
+++ b/platform/linux-dpdk/include/odp_packet_dpdk.h
@@ -81,6 +81,8 @@ typedef struct {
char ifname[32];
uint8_t portid;
uint16_t queueid;
+ odp_bool_t vdev_sysc_promisc; /**< promiscuous mode defined with
+ system call */
} pkt_dpdk_t;
/**
diff --git a/platform/linux-dpdk/odp_packet_dpdk.c b/platform/linux-dpdk/odp_packet_dpdk.c
index 472cb1b4a..2b6a8c8a3 100644
--- a/platform/linux-dpdk/odp_packet_dpdk.c
+++ b/platform/linux-dpdk/odp_packet_dpdk.c
@@ -171,6 +171,11 @@ int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
}
rte_eth_promiscuous_enable(portid);
+ /* Some DPDK PMD vdev like pcap do not support promisc mode change. Use
+ * system call for them. */
+ if (!rte_eth_promiscuous_get(portid))
+ pkt_dpdk->vdev_sysc_promisc = 1;
+
rte_eth_allmulticast_enable(portid);
return 0;
}
diff --git a/platform/linux-dpdk/odp_packet_io.c b/platform/linux-dpdk/odp_packet_io.c
index 94c8f5920..d47b3ee1a 100644
--- a/platform/linux-dpdk/odp_packet_io.c
+++ b/platform/linux-dpdk/odp_packet_io.c
@@ -702,9 +702,53 @@ int pktin_poll(pktio_entry_t *entry)
return 0;
}
+static int _dpdk_vdev_promisc_mode_set(uint8_t port_id, int enable)
+{
+ struct rte_eth_dev_info dev_info = {0};
+ struct ifreq ifr;
+ int ret;
+ int sockfd;
+
+ rte_eth_dev_info_get(port_id, &dev_info);
+ if_indextoname(dev_info.if_index, ifr.ifr_name);
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ ret = ioctl(sockfd, SIOCGIFFLAGS, &ifr);
+ if (ret < 0) {
+ close(sockfd);
+ ODP_DBG("ioctl SIOCGIFFLAGS error\n");
+ return -1;
+ }
+
+ if (enable)
+ ifr.ifr_flags |= IFF_PROMISC;
+ else
+ ifr.ifr_flags &= ~(IFF_PROMISC);
+
+ ret = ioctl(sockfd, SIOCSIFFLAGS, &ifr);
+ if (ret < 0) {
+ close(sockfd);
+ ODP_DBG("ioctl SIOCSIFFLAGS error\n");
+ return -1;
+ }
+
+ ret = ioctl(sockfd, SIOCGIFMTU, &ifr);
+ if (ret < 0) {
+ close(sockfd);
+ ODP_DBG("ioctl SIOCGIFMTU error\n");
+ return -1;
+ }
+
+ ODP_DBG("vdev promisc set to %d\n", enable);
+ close(sockfd);
+ return 0;
+}
+
int odp_pktio_promisc_mode_set(odp_pktio_t id, odp_bool_t enable)
{
pktio_entry_t *entry;
+ uint8_t portid;
+ int ret;
entry = get_pktio_entry(id);
if (entry == NULL) {
@@ -727,19 +771,51 @@ int odp_pktio_promisc_mode_set(odp_pktio_t id, odp_bool_t enable)
return 0;
}
+ portid = entry->s.pkt_dpdk.portid;
if (enable)
- rte_eth_promiscuous_enable(entry->s.pkt_dpdk.portid);
+ rte_eth_promiscuous_enable(portid);
else
- rte_eth_promiscuous_disable(entry->s.pkt_dpdk.portid);
+ rte_eth_promiscuous_disable(portid);
+
+ if (entry->s.pkt_dpdk.vdev_sysc_promisc) {
+ ret = _dpdk_vdev_promisc_mode_set(portid, enable);
+ if (ret < 0)
+ ODP_DBG("vdev promisc mode fail\n");
+ }
unlock_entry(entry);
return 0;
}
+static int _dpdk_vdev_promisc_mode(uint8_t port_id)
+{
+ struct rte_eth_dev_info dev_info = {0};
+ struct ifreq ifr;
+ int ret;
+ int sockfd;
+
+ rte_eth_dev_info_get(port_id, &dev_info);
+ if_indextoname(dev_info.if_index, ifr.ifr_name);
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ ret = ioctl(sockfd, SIOCGIFFLAGS, &ifr);
+ close(sockfd);
+ if (ret < 0) {
+ ODP_DBG("ioctl SIOCGIFFLAGS error\n");
+ return -1;
+ }
+
+ if (ifr.ifr_flags & IFF_PROMISC) {
+ ODP_DBG("promisc is 1\n");
+ return 1;
+ } else
+ return 0;
+}
+
int odp_pktio_promisc_mode(odp_pktio_t id)
{
pktio_entry_t *entry;
int promisc;
+ uint8_t portid;
entry = get_pktio_entry(id);
if (entry == NULL) {
@@ -755,7 +831,12 @@ int odp_pktio_promisc_mode(odp_pktio_t id)
return -1;
}
- promisc = rte_eth_promiscuous_get(entry->s.pkt_dpdk.portid);
+ portid = entry->s.pkt_dpdk.portid;
+
+ if (entry->s.pkt_dpdk.vdev_sysc_promisc)
+ promisc = _dpdk_vdev_promisc_mode(portid);
+ else
+ promisc = rte_eth_promiscuous_get(portid);
unlock_entry(entry);