1 /*
2 Copyright (c) 2013, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*!
30 @file
31 IPACM_Routing.cpp
32
33 @brief
34 This file implements the IPACM routing functionality.
35
36 @Author
37
38 */
39
40 #include <unistd.h>
41 #include <sys/ioctl.h>
42 #include <fcntl.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45
46 #include "IPACM_Routing.h"
47 #include <IPACM_Log.h>
48
49 const char *IPACM_Routing::DEVICE_NAME = "/dev/ipa";
50
IPACM_Routing()51 IPACM_Routing::IPACM_Routing()
52 {
53 m_fd = open(DEVICE_NAME, O_RDWR);
54 if (0 == m_fd)
55 {
56 IPACMERR("Failed opening %s.\n", DEVICE_NAME);
57 }
58 }
59
~IPACM_Routing()60 IPACM_Routing::~IPACM_Routing()
61 {
62 close(m_fd);
63 }
64
DeviceNodeIsOpened()65 bool IPACM_Routing::DeviceNodeIsOpened()
66 {
67 int res = fcntl(m_fd, F_GETFL);
68
69 if (m_fd > 0 && res >= 0) return true;
70 else return false;
71
72 }
73
AddRoutingRule(struct ipa_ioc_add_rt_rule * ruleTable)74 bool IPACM_Routing::AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable)
75 {
76 int retval = 0, cnt=0;
77 bool isInvalid = false;
78
79 if (!DeviceNodeIsOpened())
80 {
81 IPACMERR("Device is not opened\n");
82 return false;
83 }
84
85 for(cnt=0; cnt<ruleTable->num_rules; cnt++)
86 {
87 if(ruleTable->rules[cnt].rule.dst > IPA_CLIENT_MAX)
88 {
89 IPACMERR("Invalid dst pipe, Rule:%d dst_pipe:%d\n", cnt, ruleTable->rules[cnt].rule.dst);
90 isInvalid = true;
91 }
92 }
93
94 if(isInvalid)
95 {
96 return false;
97 }
98
99 retval = ioctl(m_fd, IPA_IOC_ADD_RT_RULE, ruleTable);
100 if (retval)
101 {
102 IPACMERR("Failed adding routing rule %p\n", ruleTable);
103 return false;
104 }
105
106 for(cnt=0; cnt<ruleTable->num_rules; cnt++)
107 {
108 IPACMDBG("Rule:%d dst_pipe:%d\n", cnt, ruleTable->rules[cnt].rule.dst);
109 }
110
111 IPACMDBG_H("Added routing rule %p\n", ruleTable);
112 return true;
113 }
114
DeleteRoutingRule(struct ipa_ioc_del_rt_rule * ruleTable)115 bool IPACM_Routing::DeleteRoutingRule(struct ipa_ioc_del_rt_rule *ruleTable)
116 {
117 int retval = 0;
118
119 if (!DeviceNodeIsOpened()) return false;
120
121 retval = ioctl(m_fd, IPA_IOC_DEL_RT_RULE, ruleTable);
122 if (retval)
123 {
124 IPACMERR("Failed deleting routing rule table %p\n", ruleTable);
125 return false;
126 }
127
128 IPACMDBG_H("Deleted routing rule %p\n", ruleTable);
129 return true;
130 }
131
Commit(enum ipa_ip_type ip)132 bool IPACM_Routing::Commit(enum ipa_ip_type ip)
133 {
134 int retval = 0;
135
136 if (!DeviceNodeIsOpened()) return false;
137
138 retval = ioctl(m_fd, IPA_IOC_COMMIT_RT, ip);
139 if (retval)
140 {
141 IPACMERR("Failed commiting routing rules.\n");
142 return false;
143 }
144
145 IPACMDBG_H("Commited routing rules to IPA HW.\n");
146 return true;
147 }
148
Reset(enum ipa_ip_type ip)149 bool IPACM_Routing::Reset(enum ipa_ip_type ip)
150 {
151 int retval = 0;
152
153 if (!DeviceNodeIsOpened()) return false;
154
155 retval = ioctl(m_fd, IPA_IOC_RESET_RT, ip);
156 retval |= ioctl(m_fd, IPA_IOC_COMMIT_RT, ip);
157 if (retval)
158 {
159 IPACMERR("Failed resetting routing block.\n");
160 return false;
161 }
162
163 IPACMDBG_H("Reset command issued to IPA routing block.\n");
164 return true;
165 }
166
GetRoutingTable(struct ipa_ioc_get_rt_tbl * routingTable)167 bool IPACM_Routing::GetRoutingTable(struct ipa_ioc_get_rt_tbl *routingTable)
168 {
169 int retval = 0;
170
171 if (!DeviceNodeIsOpened()) return false;
172
173 retval = ioctl(m_fd, IPA_IOC_GET_RT_TBL, routingTable);
174 if (retval)
175 {
176 IPACMERR("IPA_IOCTL_GET_RT_TBL ioctl failed, routingTable =0x%p, retval=0x%x.\n", routingTable, retval);
177 return false;
178 }
179 IPACMDBG_H("IPA_IOCTL_GET_RT_TBL ioctl issued to IPA routing block.\n");
180 /* put routing table right after successfully get routing table */
181 PutRoutingTable(routingTable->hdl);
182
183 return true;
184 }
185
PutRoutingTable(uint32_t routingTableHandle)186 bool IPACM_Routing::PutRoutingTable(uint32_t routingTableHandle)
187 {
188 int retval = 0;
189
190 if (!DeviceNodeIsOpened()) return false;
191
192 retval = ioctl(m_fd, IPA_IOC_PUT_RT_TBL, routingTableHandle);
193 if (retval)
194 {
195 IPACMERR("IPA_IOCTL_PUT_RT_TBL ioctl failed.\n");
196 return false;
197 }
198
199 IPACMDBG_H("IPA_IOCTL_PUT_RT_TBL ioctl issued to IPA routing block.\n");
200 return true;
201 }
202
DeleteRoutingHdl(uint32_t rt_rule_hdl,ipa_ip_type ip)203 bool IPACM_Routing::DeleteRoutingHdl(uint32_t rt_rule_hdl, ipa_ip_type ip)
204 {
205 const uint8_t NUM_RULES = 1;
206 struct ipa_ioc_del_rt_rule *rt_rule;
207 struct ipa_rt_rule_del *rt_rule_entry;
208 bool res = true;
209 int len = 0;
210
211 if (rt_rule_hdl == 0)
212 {
213 IPACMERR(" No route handle passed. Ignoring it\n");
214 return res;
215 }
216
217 len = (sizeof(struct ipa_ioc_del_rt_rule)) + (NUM_RULES * sizeof(struct ipa_rt_rule_del));
218 rt_rule = (struct ipa_ioc_del_rt_rule *)malloc(len);
219 if (rt_rule == NULL)
220 {
221 IPACMERR("unable to allocate memory for del route rule\n");
222 return false;
223 }
224
225 memset(rt_rule, 0, len);
226 rt_rule->commit = 1;
227 rt_rule->num_hdls = NUM_RULES;
228 rt_rule->ip = ip;
229
230 rt_rule_entry = &rt_rule->hdl[0];
231 rt_rule_entry->status = -1;
232 rt_rule_entry->hdl = rt_rule_hdl;
233
234 IPACMDBG_H("Deleting Route hdl:(0x%x) with ip type: %d\n", rt_rule_entry->hdl, ip);
235 if ((false == DeleteRoutingRule(rt_rule)) ||
236 (rt_rule_entry->status))
237 {
238 PERROR("Routing rule deletion failed!\n");
239 goto fail;
240 res = false;
241 }
242
243 fail:
244 free(rt_rule);
245
246 return res;
247 }
248
ModifyRoutingRule(struct ipa_ioc_mdfy_rt_rule * mdfyRules)249 bool IPACM_Routing::ModifyRoutingRule(struct ipa_ioc_mdfy_rt_rule *mdfyRules)
250 {
251 int retval = 0, cnt;
252
253 if (!DeviceNodeIsOpened())
254 {
255 IPACMERR("Device is not opened\n");
256 return false;
257 }
258
259 retval = ioctl(m_fd, IPA_IOC_MDFY_RT_RULE, mdfyRules);
260 if (retval)
261 {
262 IPACMERR("Failed modifying routing rules %p\n", mdfyRules);
263 return false;
264 }
265
266 for(cnt=0; cnt<mdfyRules->num_rules; cnt++)
267 {
268 if(mdfyRules->rules[cnt].status != 0)
269 {
270 IPACMERR("Unable to modify rule: %d\n", cnt);
271 }
272 }
273
274 IPACMDBG_H("Modified routing rules %p\n", mdfyRules);
275 return true;
276 }
277