Home | History | Annotate | Download | only in src
      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 
     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 
     60 IPACM_Routing::~IPACM_Routing()
     61 {
     62 	close(m_fd);
     63 }
     64 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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