summaryrefslogtreecommitdiffstats
path: root/recipes-networking/dpdk/files/rte_kni_module_1_6.patch.x
blob: 48b1849070d4517cfc24526909cd8a4ab87d3f20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
--- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h
+++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h
@@ -101,6 +101,7 @@ struct rte_kni_device_info {
 
 	/* mbuf size */
 	unsigned mbuf_size;
+	uint64_t mempool_size;
 };
 
 #define KNI_DEVICE "kni"
--- a/lib/librte_eal/linuxapp/kni/kni_misc.c
+++ b/lib/librte_eal/linuxapp/kni/kni_misc.c
@@ -21,6 +21,19 @@ MODULE_DESCRIPTION("Kernel Module for managing kni devices");
 
 #define KNI_MAX_DEVICES 32
 
+#define PCI_VENDOR_ID_IVSHMEM 0x1AF4
+#define PCI_DEVICE_ID_IVSHMEM 0x1110
+#define BAR2                  2
+#define IVSHMEM_MAGIC         0x0BADC0DE
+#define IVSHMEM_METADATA_SIZE 0x4000
+#define KNI_FIFO_COUNT_MAX    1024
+#define KNI_FIFO_SIZE         ((KNI_FIFO_COUNT_MAX) * sizeof(void *) + \
+                              sizeof(struct rte_kni_fifo))
+
+#define get_virt_addr(x) get_virt_addr_by_size(x,KNI_FIFO_SIZE)
+#define get_virt_addr_by_size(x,s) (has_ivshmem_metadata ? \
+                                    ioremap(x, s) : phys_to_virt(x))
+
 extern void kni_net_rx(struct kni_dev *kni);
 extern void kni_net_init(struct net_device *dev);
 extern void kni_net_config_lo_mode(char *lo_str);
@@ -47,6 +60,8 @@ static int kni_thread_single(void *unused);
 /* KNI processing for multiple kernel thread mode */
 static int kni_thread_multiple(void *param);
 
+static int kni_has_ivshmem_metadata(void);
+
 static struct file_operations kni_fops = {
 	.owner = THIS_MODULE,
 	.open = kni_open,
@@ -72,6 +87,7 @@ static unsigned multiple_kthread_on = 0;
 
 static volatile unsigned long device_in_use; /* device in use flag */
 static struct task_struct *kni_kthread;
+static int has_ivshmem_metadata = 0;
 
 /* kni list lock */
 static DECLARE_RWSEM(kni_list_lock);
@@ -100,6 +116,10 @@ kni_init(void)
 	/* Configure the lo mode according to the input parameter */
 	kni_net_config_lo_mode(lo_mode);
 
+	has_ivshmem_metadata = kni_has_ivshmem_metadata();
+	KNI_PRINT("IVSHMEM metadata %s \n",
+				has_ivshmem_metadata ? "found" : "NOT found");
+
 	KNI_PRINT("######## DPDK kni module loaded  ########\n");
 
 	return 0;
@@ -178,6 +198,19 @@ kni_release(struct inode *inode, struct file *file)
 #endif
 		kni_dev_remove(dev);
 		list_del(&dev->list);
+
+		if (has_ivshmem_metadata) {
+			KNI_PRINT("iounmapping KNI FIFOs for device '%s'\n", dev->name);
+			iounmap(dev->tx_q);
+			iounmap(dev->rx_q);
+			iounmap(dev->alloc_q);
+			iounmap(dev->free_q);
+			iounmap(dev->req_q);
+			iounmap(dev->resp_q);
+			iounmap(dev->sync_kva);
+			iounmap(dev->mbuf_kva);
+		}
+
 	}
 	up_write(&kni_list_lock);
 
@@ -339,17 +372,17 @@ kni_ioctl_create(unsigned int ioctl_num, unsigned long ioctl_param)
 	strncpy(kni->name, dev_info.name, RTE_KNI_NAMESIZE);
 
 	/* Translate user space info into kernel space info */
-	kni->tx_q = phys_to_virt(dev_info.tx_phys);
-	kni->rx_q = phys_to_virt(dev_info.rx_phys);
-	kni->alloc_q = phys_to_virt(dev_info.alloc_phys);
-	kni->free_q = phys_to_virt(dev_info.free_phys);
+	kni->tx_q = get_virt_addr(dev_info.tx_phys);
+	kni->rx_q = get_virt_addr(dev_info.rx_phys);
+	kni->alloc_q = get_virt_addr(dev_info.alloc_phys);
+	kni->free_q = get_virt_addr(dev_info.free_phys);
 
-	kni->req_q = phys_to_virt(dev_info.req_phys);
-	kni->resp_q = phys_to_virt(dev_info.resp_phys);
+	kni->req_q = get_virt_addr(dev_info.req_phys);
+	kni->resp_q = get_virt_addr(dev_info.resp_phys);
 	kni->sync_va = dev_info.sync_va;
-	kni->sync_kva = phys_to_virt(dev_info.sync_phys);
+	kni->sync_kva = get_virt_addr(dev_info.sync_phys);
 
-	kni->mbuf_kva = phys_to_virt(dev_info.mbuf_phys);
+	kni->mbuf_kva = get_virt_addr_by_size(dev_info.mbuf_phys, dev_info.mempool_size);
 	kni->mbuf_va = dev_info.mbuf_va;
 
 #ifdef RTE_KNI_VHOST
@@ -552,6 +585,40 @@ kni_compat_ioctl(struct inode *inode,
 	return -EINVAL;
 }
 
+static int
+kni_has_ivshmem_metadata(void)
+{
+	struct pci_dev *ivshm_dev = NULL;
+	phys_addr_t ivshmem_metadata_addr = 0;
+	void *ivshmem_metadata = NULL;
+	int ivshmem_magic_number;
+
+	ivshm_dev = pci_get_device(PCI_VENDOR_ID_IVSHMEM, PCI_DEVICE_ID_IVSHMEM,
+			NULL);
+
+	if (ivshm_dev == NULL) {
+		printk("No IVSHMEM device found!\n");
+		return 0;
+	}
+
+	/* IVSHMEM metadata will be received at the very last 4K of the BAR2 */
+	ivshmem_metadata_addr = (pci_resource_end(ivshm_dev, BAR2)
+			- IVSHMEM_METADATA_SIZE) + 1;
+
+	ivshmem_metadata = ioremap(ivshmem_metadata_addr, IVSHMEM_METADATA_SIZE);
+	if (ivshmem_metadata == NULL) {
+		printk("Could not ioremap IVSHMEM metadata\n");
+		return 0;
+	}
+
+	/* The first sizeof(int) bytes contain the magic number that tells us
+	 * ivshmem_metadata is coming from the host */
+	ivshmem_magic_number = ((int*) ivshmem_metadata)[0];
+	iounmap(ivshmem_metadata);
+	return !!(ivshmem_magic_number == IVSHMEM_MAGIC);
+}
+
+
 module_init(kni_init);
 module_exit(kni_exit);
 
--- a/lib/librte_eal/linuxapp/kni/kni_net.c
+++ b/lib/librte_eal/linuxapp/kni/kni_net.c
@@ -50,15 +50,16 @@ kni_net_open(struct net_device *dev)
 	struct rte_kni_request req;
 	struct kni_dev *kni = netdev_priv(dev);
 
-	if (kni->lad_dev)
-		memcpy(dev->dev_addr, kni->lad_dev->dev_addr, ETH_ALEN);
-	else
-		/*
-		 * Generate random mac address. eth_random_addr() is the newer
-		 * version of generating mac address in linux kernel.
-		 */
-		random_ether_addr(dev->dev_addr);
-
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		if (kni->lad_dev)
+			memcpy(dev->dev_addr, kni->lad_dev->dev_addr, ETH_ALEN);
+		else
+			/*
+			 * Generate random mac address. eth_random_addr() is the newer
+			 * version of generating mac address in linux kernel.
+			 */
+			random_ether_addr(dev->dev_addr);
+	}
 	netif_start_queue(dev);
 
 	memset(&req, 0, sizeof(req));
@@ -459,6 +460,22 @@ kni_net_tx_timeout (struct net_device *dev)
 	return;
 }
 
+static int
+kni_set_mac_address(struct net_device *dev, void *addr_ptr)
+{
+	struct sockaddr *addr = addr_ptr;
+
+	if (netif_running(dev))
+		return -EBUSY;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	return 0;
+}
+
 /*
  * Ioctl commands
  */
@@ -608,6 +625,7 @@ static const struct net_device_ops kni_net_netdev_ops = {
 	.ndo_do_ioctl = kni_net_ioctl,
 	.ndo_get_stats = kni_net_stats,
 	.ndo_tx_timeout = kni_net_tx_timeout,
+	.ndo_set_mac_address = kni_set_mac_address,
 };
 
 void