Line data Source code
1 : /*
2 : * vr_dpdk_ddp.c - DDP specific API's for adding/deleting the firmware.
3 : *
4 : * Copyright (c) 2020 Juniper Networks, Inc. All rights reserved.
5 : * Copyright Contributors to the OpenSDN project
6 : */
7 : #include <sys/types.h>
8 : #include <sys/stat.h>
9 : #include <fcntl.h>
10 :
11 : #include "vr_dpdk.h"
12 :
13 : #include <rte_eth_bond.h>
14 : #include <rte_pmd_i40e.h>
15 : #include <rte_errno.h>
16 :
17 : /* By default, DDP disabled for X710 series NIC's, pass --ddp command line
18 : * argument to enable it */
19 : static bool vr_dpdk_enable_ddp = false;
20 : const char ddp_fpath[] = "/opt/contrail/ddp/mplsogreudp.pkg";
21 : const char ddp_fbkp[] = "/opt/contrail/ddp/mplsogreudp.bkp";
22 :
23 :
24 : bool
25 0 : vr_dpdk_get_ddp(void)
26 : {
27 0 : return vr_dpdk_enable_ddp;
28 : }
29 :
30 : void
31 0 : vr_dpdk_set_ddp(void)
32 : {
33 0 : vr_dpdk_enable_ddp = true;
34 0 : }
35 :
36 : void
37 0 : vr_dpdk_reset_ddp(void)
38 : {
39 0 : vr_dpdk_enable_ddp = false;
40 0 : }
41 :
42 : static int
43 0 : vr_dpdk_ddp_add(uint16_t port_id)
44 : {
45 0 : int ddp_fd, ret = -ENOTSUP;
46 : uint8_t *buf;
47 : struct stat st_buf;
48 : FILE *ddp_bkp_fd;
49 :
50 0 : if(!rte_eth_dev_is_valid_port(port_id)) {
51 0 : RTE_LOG(ERR, VROUTER, "%s : DDP port_id is invalid \n", __func__);
52 0 : return VR_DPDK_DDP_FAILED;
53 : }
54 :
55 0 : ddp_fd = open(ddp_fpath, O_RDONLY);
56 0 : if(ddp_fd == -1) {
57 0 : RTE_LOG(ERR, VROUTER, "%s: Failed to open %s file \n",
58 : __func__, ddp_fpath);
59 0 : return VR_DPDK_DDP_FAILED;
60 : }
61 0 : if ((fstat(ddp_fd, &st_buf) != 0) || (!S_ISREG(st_buf.st_mode))) {
62 0 : close(ddp_fd);
63 0 : RTE_LOG(ERR, VROUTER, "%s: File operation failed for %s\n",
64 : __func__, ddp_fpath);
65 0 : return VR_DPDK_DDP_FAILED;
66 : }
67 :
68 0 : if(st_buf.st_size < 0) {
69 0 : close(ddp_fd);
70 0 : RTE_LOG(ERR, VROUTER, "%s: File operation failed for %s while reading"
71 : "size %ld \n", __func__, ddp_fpath, st_buf.st_size);
72 0 : return VR_DPDK_DDP_FAILED;
73 : }
74 :
75 0 : buf = (uint8_t *)vr_zalloc(st_buf.st_size, VR_INFO_REQ_OBJECT);
76 0 : if(!buf) {
77 0 : close(ddp_fd);
78 0 : RTE_LOG(ERR, VROUTER, "%s: Memory allocation failed for size %ld\n",
79 : __func__, st_buf.st_size);
80 0 : return VR_DPDK_DDP_FAILED;
81 : }
82 :
83 0 : ret = read(ddp_fd, buf, st_buf.st_size);
84 0 : if(ret < 0) {
85 0 : close(ddp_fd);
86 0 : vr_free(buf, VR_INFO_REQ_OBJECT);
87 0 : RTE_LOG(ERR, VROUTER, "%s: File read operation failed for %s\n",
88 : __func__, ddp_fpath);
89 0 : return VR_DPDK_DDP_FAILED;
90 : }
91 :
92 0 : ret = rte_pmd_i40e_process_ddp_package(port_id, buf, st_buf.st_size,
93 : RTE_PMD_I40E_PKG_OP_WR_ADD);
94 :
95 0 : if(ret == -ENOTSUP) {
96 0 : RTE_LOG(ERR, VROUTER, "%s: DDP works only on X710 NIC series \n",
97 : __func__);
98 0 : } else if (ret == -EEXIST) {
99 0 : RTE_LOG(DEBUG, VROUTER, "%s: DDP Profile already exist\n", __func__);
100 0 : } else if(ret < 0) {
101 0 : RTE_LOG(ERR, VROUTER, "%s: Failed to load profile return value is %d\n",
102 : __func__, ret);
103 : } else {
104 0 : RTE_LOG(INFO, VROUTER, "%s DDP programming was successful\n",
105 : __func__);
106 0 : ddp_bkp_fd = fopen(ddp_fbkp, "wb");
107 0 : if(ddp_bkp_fd == NULL) {
108 0 : close(ddp_fd);
109 0 : vr_free(buf, VR_INFO_REQ_OBJECT);
110 0 : RTE_LOG(ERR, VROUTER, "%s: Failed to open %s\n",
111 : __func__, ddp_fbkp);
112 0 : return VR_DPDK_DDP_FAILED;
113 : }
114 :
115 0 : if(fwrite(buf, 1, st_buf.st_size, ddp_bkp_fd) != st_buf.st_size) {
116 0 : close(ddp_fd);
117 0 : fclose(ddp_bkp_fd);
118 0 : vr_free(buf, VR_INFO_REQ_OBJECT);
119 0 : RTE_LOG(ERR, VROUTER, "%s: Failed to write %s\n", __func__, ddp_fbkp);
120 0 : return VR_DPDK_DDP_FAILED;
121 : }
122 0 : fclose(ddp_bkp_fd);
123 : }
124 :
125 0 : if (ddp_fd) {
126 0 : close(ddp_fd);
127 : }
128 :
129 0 : if (buf) {
130 0 : vr_free(buf, VR_INFO_REQ_OBJECT);
131 : }
132 :
133 0 : return ret;
134 : }
135 :
136 : static int
137 0 : vr_dpdk_ddp_del(uint16_t port_id)
138 : {
139 0 : int ddp_fd, ret = -ENOTSUP;
140 : uint8_t *buf;
141 : struct stat st_buf;
142 :
143 0 : if(!rte_eth_dev_is_valid_port(port_id)) {
144 0 : RTE_LOG(ERR, VROUTER, "%s: DDP port_id is invalid \n", __func__);
145 0 : return VR_DPDK_DDP_FAILED;
146 : }
147 :
148 0 : ddp_fd = open(ddp_fbkp, O_RDONLY);
149 0 : if(ddp_fd == -1) {
150 0 : RTE_LOG(ERR, VROUTER, "%s: Failed to open %s file\n", __func__,
151 : ddp_fbkp);
152 0 : return VR_DPDK_DDP_FAILED;
153 : }
154 :
155 0 : if ((fstat(ddp_fd, &st_buf) != 0) || (!S_ISREG(st_buf.st_mode))) {
156 0 : close(ddp_fd);
157 0 : RTE_LOG(ERR, VROUTER, "%s: File operation failed for %s\n",
158 : __func__, ddp_fbkp);
159 0 : return VR_DPDK_DDP_FAILED;
160 : }
161 :
162 0 : if(st_buf.st_size < 0) {
163 0 : close(ddp_fd);
164 0 : RTE_LOG(ERR, VROUTER, "%s: File operation failed for %s while reading"
165 : "size %ld \n", __func__, ddp_fbkp, st_buf.st_size);
166 0 : return VR_DPDK_DDP_FAILED;
167 : }
168 :
169 0 : buf = (uint8_t *)vr_zalloc(st_buf.st_size, VR_INFO_REQ_OBJECT);
170 0 : if(!buf) {
171 0 : close(ddp_fd);
172 0 : RTE_LOG(ERR, VROUTER, "%s: Memory allocation failed for size %ld\n",
173 : __func__, st_buf.st_size);
174 0 : return VR_DPDK_DDP_FAILED;
175 : }
176 :
177 0 : ret = read(ddp_fd, buf, st_buf.st_size);
178 0 : if(ret < 0) {
179 0 : close(ddp_fd);
180 0 : vr_free(buf, VR_INFO_REQ_OBJECT);
181 0 : RTE_LOG(ERR, VROUTER, "%s: File read operation failed for %s\n",
182 : __func__, ddp_fbkp);
183 0 : return VR_DPDK_DDP_FAILED;
184 : }
185 :
186 0 : ret = rte_pmd_i40e_process_ddp_package(port_id, buf, st_buf.st_size,
187 : RTE_PMD_I40E_PKG_OP_WR_DEL);
188 0 : if(ret == -ENOTSUP) {
189 0 : RTE_LOG(ERR, VROUTER, "%s: DDP works only on X710 NIC series\n",
190 : __func__);
191 0 : } else if(ret == -EACCES) {
192 0 : RTE_LOG(DEBUG, VROUTER, "%s: DDP profile doesn't exist\n", __func__);
193 0 : } else if(ret < 0) {
194 0 : RTE_LOG(ERR, VROUTER, "%s: Failed to delete profile return value is %d\n",
195 : __func__, ret);
196 : } else {
197 0 : RTE_LOG(INFO, VROUTER, "%s: Removed DDP image mplsogreudp - success\n",
198 : __func__);
199 : }
200 :
201 0 : if(ddp_fd) {
202 0 : close(ddp_fd);
203 : }
204 :
205 0 : if(buf) {
206 0 : vr_free(buf, VR_INFO_REQ_OBJECT);
207 : }
208 :
209 0 : return ret;
210 : }
211 :
212 : int
213 0 : vr_dpdk_process_ddp_package(unsigned ddp_op)
214 : {
215 : int i, ret;
216 : struct vr_dpdk_ethdev *ethdev;
217 : struct rte_eth_dev *dev;
218 0 : uint16_t slave_port_id, port_id = vr_dpdk_master_port_id;
219 :
220 0 : if(rte_eth_dev_is_valid_port(port_id)) {
221 0 : ethdev = &vr_dpdk.ethdevs[port_id];
222 :
223 0 : if (ethdev->ethdev_nb_slaves > 0) {
224 0 : for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
225 0 : slave_port_id = ethdev->ethdev_slaves[i];
226 0 : dev = &rte_eth_devices[slave_port_id];
227 0 : if(!strcmp(dev->device->driver->name, "net_i40e")) {
228 0 : if(ddp_op == VR_DPDK_DDP_ADD) {
229 0 : ret = vr_dpdk_ddp_add((uint16_t)slave_port_id);
230 0 : if(!(ret == -EEXIST || ret == 0))
231 0 : return ret;
232 0 : } else if(ddp_op == VR_DPDK_DDP_DELETE) {
233 0 : ret = vr_dpdk_ddp_del((uint16_t)slave_port_id);
234 0 : if(!(ret == -EACCES || ret == 0))
235 0 : return ret;
236 : }
237 : } else {
238 0 : RTE_LOG(DEBUG, VROUTER, "%s: DDP supports only on X710 series"
239 : "NIC cardsi\n", __func__);
240 0 : return VR_DPDK_DDP_NOT_SUPPORTED;
241 : }
242 : }
243 : } else {
244 0 : dev = &rte_eth_devices[ethdev->ethdev_port_id];
245 0 : if(!strcmp(dev->device->driver->name, "net_i40e")) {
246 0 : if(ddp_op == VR_DPDK_DDP_ADD) {
247 0 : return vr_dpdk_ddp_add((uint16_t)ethdev->ethdev_port_id);
248 0 : } else if(ddp_op == VR_DPDK_DDP_DELETE) {
249 0 : return vr_dpdk_ddp_del((uint16_t)ethdev->ethdev_port_id);
250 : }
251 : } else {
252 0 : RTE_LOG(DEBUG, VROUTER, "%s: DDP supports only on X710 series"
253 : "NIC cards", __func__);
254 0 : return VR_DPDK_DDP_NOT_SUPPORTED;
255 : }
256 : }
257 : }
258 0 : return 0;
259 : }
|