/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2007,2008, 2009 INRIA, UDcast
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
*/
#include "ipcs-classifier-record.h"
#include <stdint.h>
#include "ns3/ipv4-address.h"
#include "wimax-tlv.h"
NS_LOG_COMPONENT_DEFINE ("IpcsClassifierRecord");
namespace ns3 {
IpcsClassifierRecord::IpcsClassifierRecord (void)
{
m_priority = 255;
m_priority = 0;
m_index = 0;
m_tosLow = 0;
m_tosHigh = 0;
m_tosMask = 0;
m_cid = 0;
m_protocol.push_back (6); // tcp
m_protocol.push_back (17); // udp
AddSrcAddr (Ipv4Address ("0.0.0.0"), Ipv4Mask ("0.0.0.0"));
AddDstAddr (Ipv4Address ("0.0.0.0"), Ipv4Mask ("0.0.0.0"));
AddSrcPortRange (0, 65535);
AddDstPortRange (0, 65535);
}
IpcsClassifierRecord::~IpcsClassifierRecord (void)
{
}
IpcsClassifierRecord::IpcsClassifierRecord (Tlv tlv)
{
NS_ASSERT_MSG (tlv.GetType () == CsParamVectorTlvValue::Packet_Classification_Rule, "Invalid TLV");
ClassificationRuleVectorTlvValue* rules = ((ClassificationRuleVectorTlvValue*)(tlv.PeekValue ()));
m_priority = 0;
m_index = 0;
m_tosLow = 0;
m_tosHigh = 0;
m_tosMask = 0;
m_cid = 0;
for (std::vector<Tlv*>::const_iterator iter = rules->Begin (); iter != rules->End (); ++iter)
{
switch ((*iter)->GetType ())
{
case ClassificationRuleVectorTlvValue::Priority:
{
m_priority = ((U8TlvValue*)((*iter)->PeekValue ()))->GetValue ();
break;
}
case ClassificationRuleVectorTlvValue::ToS:
{
NS_FATAL_ERROR ("ToS Not implemented-- please implement and contribute a patch");
break;
}
case ClassificationRuleVectorTlvValue::Protocol:
{
ProtocolTlvValue * list = (ProtocolTlvValue *)(*iter)->PeekValue ();
for (std::vector<uint8_t>::const_iterator iter2 = list->Begin (); iter2 != list->End (); ++iter2)
{
AddProtocol (*iter2);
}
break;
}
case ClassificationRuleVectorTlvValue::IP_src:
{
Ipv4AddressTlvValue * list = (Ipv4AddressTlvValue *)(*iter)->PeekValue ();
for (std::vector<Ipv4AddressTlvValue::ipv4Addr>::const_iterator iter2 = list->Begin (); iter2 != list->End (); ++iter2)
{
AddSrcAddr ((*iter2).Address, (*iter2).Mask);
}
break;
}
case ClassificationRuleVectorTlvValue::IP_dst:
{
Ipv4AddressTlvValue * list = (Ipv4AddressTlvValue *)(*iter)->PeekValue ();
for (std::vector<Ipv4AddressTlvValue::ipv4Addr>::const_iterator iter2 = list->Begin (); iter2 != list->End (); ++iter2)
{
AddDstAddr ((*iter2).Address, (*iter2).Mask);
}
break;
}
case ClassificationRuleVectorTlvValue::Port_src:
{
PortRangeTlvValue * list = (PortRangeTlvValue *)(*iter)->PeekValue ();
for (std::vector<PortRangeTlvValue::PortRange>::const_iterator iter2 = list->Begin (); iter2 != list->End (); ++iter2)
{
AddSrcPortRange ((*iter2).PortLow, (*iter2).PortHigh);
}
break;
}
case ClassificationRuleVectorTlvValue::Port_dst:
{
PortRangeTlvValue * list = (PortRangeTlvValue *)(*iter)->PeekValue ();
for (std::vector<PortRangeTlvValue::PortRange>::const_iterator iter2 = list->Begin (); iter2 != list->End (); ++iter2)
{
AddDstPortRange ((*iter2).PortLow, (*iter2).PortHigh);
}
break;
}
case ClassificationRuleVectorTlvValue::Index:
{
m_index = ((U16TlvValue*)((*iter)->PeekValue ()))->GetValue ();
break;
}
}
}
}
IpcsClassifierRecord::IpcsClassifierRecord (Ipv4Address SrcAddress,
Ipv4Mask SrcMask,
Ipv4Address DstAddress,
Ipv4Mask DstMask,
uint16_t SrcPortLow,
uint16_t SrcPortHigh,
uint16_t DstPortLow,
uint16_t DstPortHigh,
uint8_t protocol,
uint8_t priority)
{
m_priority = priority;
m_protocol.push_back (protocol);
AddSrcAddr (SrcAddress, SrcMask);
AddDstAddr (DstAddress, DstMask);
AddSrcPortRange (SrcPortLow, SrcPortHigh);
AddDstPortRange (DstPortLow, DstPortHigh);
m_index = 0;
m_tosLow = 0;
m_tosHigh = 0;
m_tosMask = 0;
m_cid = 0;
}
void
IpcsClassifierRecord::AddSrcAddr (Ipv4Address srcAddress, Ipv4Mask srcMask)
{
struct ipv4Addr tmp;
tmp.Address = srcAddress;
tmp.Mask = srcMask;
m_srcAddr.push_back (tmp);
}
void
IpcsClassifierRecord::AddDstAddr (Ipv4Address dstAddress, Ipv4Mask dstMask)
{
struct ipv4Addr tmp;
tmp.Address = dstAddress;
tmp.Mask = dstMask;
m_dstAddr.push_back (tmp);
}
void
IpcsClassifierRecord::AddSrcPortRange (uint16_t srcPortLow, uint16_t srcPortHigh)
{
struct PortRange tmp;
tmp.PortLow = srcPortLow;
tmp.PortHigh = srcPortHigh;
m_srcPortRange.push_back (tmp);
}
void
IpcsClassifierRecord::AddDstPortRange (uint16_t dstPortLow, uint16_t dstPortHigh)
{
struct PortRange tmp;
tmp.PortLow = dstPortLow;
tmp.PortHigh = dstPortHigh;
m_dstPortRange.push_back (tmp);
}
void
IpcsClassifierRecord::AddProtocol (uint8_t proto)
{
m_protocol.push_back (proto);
}
void
IpcsClassifierRecord::SetPriority (uint8_t prio)
{
m_priority = prio;
}
void
IpcsClassifierRecord::SetCid (uint16_t cid)
{
m_cid = cid;
}
void
IpcsClassifierRecord::SetIndex (uint16_t index)
{
m_index = index;
}
uint16_t
IpcsClassifierRecord::GetIndex (void) const
{
return m_index;
}
uint16_t
IpcsClassifierRecord::GetCid (void) const
{
return m_cid;
}
uint8_t
IpcsClassifierRecord::GetPriority (void) const
{
return m_priority;
}
bool
IpcsClassifierRecord::CheckMatchSrcAddr (Ipv4Address srcAddress) const
{
for (std::vector<struct ipv4Addr>::const_iterator iter = m_srcAddr.begin (); iter != m_srcAddr.end (); ++iter)
{
NS_LOG_INFO ("src addr check match: pkt=" << srcAddress << " cls=" << (*iter).Address << "/" << (*iter).Mask);
if (srcAddress.CombineMask ((*iter).Mask) == (*iter).Address)
{
return true;
}
}
NS_LOG_INFO ("NOT OK!");
return false;
}
bool
IpcsClassifierRecord::CheckMatchDstAddr (Ipv4Address dstAddress) const
{
for (std::vector<struct ipv4Addr>::const_iterator iter = m_dstAddr.begin (); iter != m_dstAddr.end (); ++iter)
{
NS_LOG_INFO ("dst addr check match: pkt=" << dstAddress << " cls=" << (*iter).Address << "/" << (*iter).Mask);
if (dstAddress.CombineMask ((*iter).Mask) == (*iter).Address)
{
return true;
}
}
NS_LOG_INFO ("NOT OK!");
return false;
}
bool
IpcsClassifierRecord::CheckMatchSrcPort (uint16_t port) const
{
for (std::vector<struct PortRange>::const_iterator iter = m_srcPortRange.begin (); iter != m_srcPortRange.end (); ++iter)
{
NS_LOG_INFO ("src port check match: pkt=" << port << " cls= [" << (*iter).PortLow << " TO " << (*iter).PortHigh
<< "]");
if (port >= (*iter).PortLow && port <= (*iter).PortHigh)
{
return true;
}
}
NS_LOG_INFO ("NOT OK!");
return false;
}
bool
IpcsClassifierRecord::CheckMatchDstPort (uint16_t port) const
{
for (std::vector<struct PortRange>::const_iterator iter = m_dstPortRange.begin (); iter != m_dstPortRange.end (); ++iter)
{
NS_LOG_INFO ("dst port check match: pkt=" << port << " cls= [" << (*iter).PortLow << " TO " << (*iter).PortHigh
<< "]");
if (port >= (*iter).PortLow && port <= (*iter).PortHigh)
{
return true;
}
}
NS_LOG_INFO ("NOT OK!");
return false;
}
bool
IpcsClassifierRecord::CheckMatchProtocol (uint8_t proto) const
{
for (std::vector<uint8_t>::const_iterator iter = m_protocol.begin (); iter != m_protocol.end (); ++iter)
{
NS_LOG_INFO ("proto check match: pkt=" << (uint16_t) proto << " cls=" << (uint16_t) proto);
if (proto == (*iter))
{
return true;
}
}
NS_LOG_INFO ("NOT OK!");
return false;
}
bool
IpcsClassifierRecord::CheckMatch (Ipv4Address srcAddress,
Ipv4Address dstAddress,
uint16_t srcPort,
uint16_t dstPort,
uint8_t proto) const
{
return (CheckMatchProtocol (proto) && CheckMatchDstPort (dstPort) && CheckMatchSrcPort (srcPort)
&& CheckMatchDstAddr (dstAddress) && CheckMatchSrcAddr (srcAddress));
}
Tlv
IpcsClassifierRecord::ToTlv (void) const
{
Ipv4AddressTlvValue ipv4AddrValSrc;
for (std::vector<struct ipv4Addr>::const_iterator iter = m_srcAddr.begin (); iter != m_srcAddr.end (); ++iter)
{
ipv4AddrValSrc.Add ((*iter).Address, (*iter).Mask);
}
Ipv4AddressTlvValue ipv4AddrValDst;
for (std::vector<struct ipv4Addr>::const_iterator iter = m_dstAddr.begin (); iter != m_dstAddr.end (); ++iter)
{
ipv4AddrValDst.Add ((*iter).Address, (*iter).Mask);
}
ProtocolTlvValue protoVal;
for (std::vector<uint8_t>::const_iterator iter = m_protocol.begin (); iter != m_protocol.end (); ++iter)
{
protoVal.Add ((*iter));
}
PortRangeTlvValue portValueSrc;
for (std::vector<struct PortRange>::const_iterator iter = m_srcPortRange.begin (); iter != m_srcPortRange.end (); ++iter)
{
portValueSrc.Add ((*iter).PortLow, (*iter).PortHigh);
}
PortRangeTlvValue portValueDst;
for (std::vector<struct PortRange>::const_iterator iter = m_dstPortRange.begin (); iter != m_dstPortRange.end (); ++iter)
{
portValueDst.Add ((*iter).PortLow, (*iter).PortHigh);
}
ClassificationRuleVectorTlvValue ClassVectVal;
ClassVectVal.Add (Tlv (ClassificationRuleVectorTlvValue::Priority, 1, U8TlvValue (m_priority)));
ClassVectVal.Add (Tlv (ClassificationRuleVectorTlvValue::Protocol, protoVal.GetSerializedSize (), protoVal));
ClassVectVal.Add (Tlv (ClassificationRuleVectorTlvValue::IP_src, ipv4AddrValSrc.GetSerializedSize (), ipv4AddrValSrc));
ClassVectVal.Add (Tlv (ClassificationRuleVectorTlvValue::IP_dst, ipv4AddrValDst.GetSerializedSize (), ipv4AddrValDst));
ClassVectVal.Add (Tlv (ClassificationRuleVectorTlvValue::Port_src, portValueSrc.GetSerializedSize (), portValueSrc));
ClassVectVal.Add (Tlv (ClassificationRuleVectorTlvValue::Port_dst, portValueDst.GetSerializedSize (), portValueDst));
ClassVectVal.Add (Tlv (ClassificationRuleVectorTlvValue::Index, 2, U16TlvValue (1)));
Tlv tmp_tlv (CsParamVectorTlvValue::Packet_Classification_Rule, ClassVectVal.GetSerializedSize (), ClassVectVal);
return tmp_tlv;
}
} // namespace ns3