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