Skip to content

Commit

Permalink
Agent IPv6 flow changes
Browse files Browse the repository at this point in the history
Change-Id: I7d0b5bc164a2ec1a86cee29fc182a74c0ef2cf30
Partial-Bug: #1398625
  • Loading branch information
ashoksr committed Mar 25, 2015
1 parent f532db1 commit 113cbc7
Show file tree
Hide file tree
Showing 22 changed files with 1,468 additions and 107 deletions.
19 changes: 13 additions & 6 deletions src/ksync/ksync_sock_user.cc
Expand Up @@ -16,6 +16,7 @@
#include <boost/bind.hpp>

#include <base/logging.h>
#include <net/address_util.h>
#include <db/db.h>
#include <db/db_entry.h>
#include <db/db_table.h>
Expand Down Expand Up @@ -566,15 +567,21 @@ void KSyncSockTypeMap::SetFlowEntry(vr_flow_req *req, bool set) {
return;
}

int family = (req->get_fr_family() == AF_INET)? Address::INET :
Address::INET6;
IpAddress sip, dip;
VectorToIp(req->get_fr_flow_ip(), family, &sip, &dip);
f->fe_flags |= VR_FLOW_FLAG_ACTIVE;
f->fe_stats.flow_bytes = 30;
f->fe_stats.flow_packets = 1;
f->fe_key.flow4_sip = req->get_fr_flow_sip();
f->fe_key.flow4_dip = req->get_fr_flow_dip();
f->fe_key.flow4_sport = req->get_fr_flow_sport();
f->fe_key.flow4_dport = req->get_fr_flow_dport();
f->fe_key.flow4_nh_id = req->get_fr_flow_nh_id();
f->fe_key.flow4_proto = req->get_fr_flow_proto();
if (sip.is_v4()) {
f->fe_key.flow4_sip = sip.to_v4().to_ulong();
f->fe_key.flow4_dip = dip.to_v4().to_ulong();
}
f->fe_key.flow_sport = req->get_fr_flow_sport();
f->fe_key.flow_dport = req->get_fr_flow_dport();
f->fe_key.flow_nh_id = req->get_fr_flow_nh_id();
f->fe_key.flow_proto = req->get_fr_flow_proto();
}

void KSyncSockTypeMap::IncrFlowStats(int idx, int pkts, int bytes) {
Expand Down
126 changes: 126 additions & 0 deletions src/net/address_util.cc
Expand Up @@ -79,6 +79,61 @@ uint32_t NetmaskToPrefix(uint32_t netmask) {
return count;
}

IpAddress PrefixToIp6Netmask(uint32_t plen) {
if (plen == 0) {
return IpAddress(Ip6Address());
}

if (plen == 128) {
boost::system::error_code ec;
Ip6Address all_fs = Ip6Address::from_string
("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", ec);
return IpAddress(all_fs);
}

boost::array<uint8_t, 16> bytes;

int index = (int) (plen / 8);
int remain_mask = plen % 8;

for (int i = 0; i < index; i++) {
bytes.at(i) = 0xff;
}

switch (remain_mask) {
case 0:
bytes.at(index++) = 0;
break;
case 1:
bytes.at(index++) = 0x80;
break;
case 2:
bytes.at(index++) = 0xc0;
break;
case 3:
bytes.at(index++) = 0xe0;
break;
case 4:
bytes.at(index++) = 0xf0;
break;
case 5:
bytes.at(index++) = 0xf8;
break;
case 6:
bytes.at(index++) = 0xfc;
break;
case 7:
bytes.at(index++) = 0xfe;
break;
}

for (int i = index; i < 16; ++i) {
bytes.at(i) = 0;
}

return IpAddress(Ip6Address(bytes));
}

// Validate a list of <ip-address>:<port> endpoints.
bool ValidateServerEndpoints(std::vector<std::string> list,
std::string *error_msg) {
Expand Down Expand Up @@ -138,3 +193,74 @@ std::string GetVNFromRoutingInstance(const std::string &vn) {
if (tokens.size() < 3) return "";
return tokens[0] + ":" + tokens[1] + ":" + tokens[2];
}

/* The sandesh data-structure used for communicating flows between agent and
* vrouter represents source and destination IP (both v4 and v6) as a vector
* of bytes. The below API is used to convert source and destination IP from
* vector to either Ip4Address or Ip6Address based on family.
*/
void VectorToIp(const std::vector<int8_t> &ip, int family, IpAddress *sip,
IpAddress *dip) {
if (family == Address::INET) {
assert(ip.size() >= 8);
boost::array<unsigned char, 4> sbytes;
boost::array<unsigned char, 4> dbytes;
for (int i = 0; i < 4; i++) {
sbytes[i] = ip.at(i);
dbytes[i] = ip.at((i + 4));
}
*sip = Ip4Address(sbytes);
*dip = Ip4Address(dbytes);
} else {
boost::array<unsigned char, 16> sbytes;
boost::array<unsigned char, 16> dbytes;
assert(ip.size() >= 32);
for (int i = 0; i < 16; i++) {
sbytes[i] = ip.at(i);
dbytes[i] = ip.at((i + 16));
}
*sip = Ip6Address(sbytes);
*dip = Ip6Address(dbytes);
}
}

/* The flow data-structure represented by vrouter has source and destination IP
* address as single char array for both V4 and V6. The below API is used to
* convert Source IP and destination IP from char array to either Ip4Address
* or Ip6Address based on family.
*/
void CharArrayToIp(const unsigned char *ip, int size, int family,
IpAddress *sip, IpAddress *dip) {
if (family == Address::INET) {
assert(size >= 8);
boost::array<unsigned char, 4> sbytes;
boost::array<unsigned char, 4> dbytes;
for (int i = 0; i < 4; i++) {
sbytes[i] = ip[i];
dbytes[i] = ip[i + 4];
}
*sip = Ip4Address(sbytes);
*dip = Ip4Address(dbytes);
} else {
assert(size >= 32);
boost::array<unsigned char, 16> sbytes;
boost::array<unsigned char, 16> dbytes;
for (int i = 0; i < 16; i++) {
sbytes[i] = ip[i];
dbytes[i] = ip[i + 16];
}
*sip = Ip6Address(sbytes);
*dip = Ip6Address(dbytes);
}
}

void Ip6AddressToU64Array(const Ip6Address &addr, uint64_t *arr, int size) {
uint32_t *words;
if (size != 2)
return;
words = (uint32_t *) (addr.to_bytes().c_array());
arr[0] = (((uint64_t)words[0] << 32) & 0xFFFFFFFF00000000U) |
((uint64_t)words[1] & 0x00000000FFFFFFFFU);
arr[1] = (((uint64_t)words[2] << 32) & 0xFFFFFFFF00000000U) |
((uint64_t)words[3] & 0x00000000FFFFFFFFU);
}
7 changes: 7 additions & 0 deletions src/net/address_util.h
Expand Up @@ -37,6 +37,13 @@ bool ValidateIPAddressString(std::string ip_address_str,
IpAddress PrefixToIpNetmask(uint32_t prefix_len);
uint32_t NetmaskToPrefix(uint32_t netmask);

IpAddress PrefixToIp6Netmask(uint32_t plen);
void VectorToIp(const std::vector<int8_t> &ip, int family, IpAddress *sip,
IpAddress *dip);
void CharArrayToIp(const unsigned char *ip, int size, int family,
IpAddress *sip, IpAddress *dip);
void Ip6AddressToU64Array(const Ip6Address &addr, uint64_t *arr, int size);

bool ValidateServerEndpoints(std::vector<std::string> list,
std::string *error_msg);

Expand Down
20 changes: 10 additions & 10 deletions src/vnsw/agent/filter/acl.cc
Expand Up @@ -768,12 +768,12 @@ bool AclEntrySpec::Populate(const MatchConditionType *match_condition) {
ACL_TRACE(Err, "Invalid source ip prefix");
return false;
}
if (!src_ip_addr.is_v4()) {
ACL_TRACE(Err, "Only ipv4 supported");
return false;
}
src_ip_plen = st.ip_prefix_len;
src_ip_mask = PrefixToIpNetmask(st.ip_prefix_len);
if (src_ip_addr.is_v4()) {
src_ip_mask = PrefixToIpNetmask(st.ip_prefix_len);
} else{
src_ip_mask = PrefixToIp6Netmask(st.ip_prefix_len);
}
src_addr_type = AddressMatch::IP_ADDR;
} else if (match_condition->src_address.virtual_network.size()) {
std::string nt;
Expand All @@ -796,12 +796,12 @@ bool AclEntrySpec::Populate(const MatchConditionType *match_condition) {
ACL_TRACE(Err, "Invalid destination ip prefix");
return false;
}
if (!dst_ip_addr.is_v4()) {
ACL_TRACE(Err, "Only ipv4 supported");
return false;
}
dst_ip_plen = st.ip_prefix_len;
dst_ip_mask = PrefixToIpNetmask(st.ip_prefix_len);
if (dst_ip_addr.is_v4()) {
dst_ip_mask = PrefixToIpNetmask(st.ip_prefix_len);
} else {
dst_ip_mask = PrefixToIp6Netmask(st.ip_prefix_len);
}
dst_addr_type = AddressMatch::IP_ADDR;
} else if (match_condition->dst_address.virtual_network.size()) {
std::string nt;
Expand Down
10 changes: 7 additions & 3 deletions src/vnsw/agent/kstate/flow_kstate.cc
Expand Up @@ -3,7 +3,7 @@
*/

#include <base/task.h>
#include <base/util.h>
#include <net/address_util.h>

#include <cmn/agent_cmn.h>
#include <kstate/kstate.h>
Expand Down Expand Up @@ -75,14 +75,18 @@ void FlowKState::SetFlowData(vector<KFlowInfo> &list,
const vr_flow_entry *k_flow,
const int index) const {
KFlowInfo data;
int family = (k_flow->fe_key.flow_family == AF_INET)? Address::INET :
Address::INET6;
IpAddress sip, dip;
CharArrayToIp(k_flow->fe_key.flow_ip, sizeof(k_flow->fe_key.flow_ip),
family, &sip, &dip);

string action_str;
string flag_str;
data.set_index((unsigned int)index);
data.set_sport((unsigned)ntohs(k_flow->fe_key.flow4_sport));
data.set_dport((unsigned)ntohs(k_flow->fe_key.flow4_dport));
Ip4Address sip(ntohl(k_flow->fe_key.flow4_sip));
data.set_sip(sip.to_string());
Ip4Address dip(ntohl(k_flow->fe_key.flow4_dip));
data.set_dip(dip.to_string());
data.set_vrf_id(k_flow->fe_vrf);
data.set_proto(k_flow->fe_key.flow4_proto);
Expand Down
2 changes: 1 addition & 1 deletion src/vnsw/agent/pkt/flow_proto.h
Expand Up @@ -34,7 +34,7 @@ class FlowProto : public Proto {
FLOW_TRACE(DetailErr, msg->agent_hdr.cmd_param,
msg->agent_hdr.ifindex, msg->agent_hdr.vrf,
msg->ether_type, 0, "Flow : Non-IP packet. Dropping",
msg->l3_forwarding);
msg->l3_forwarding, 0, 0, 0, 0);
return false;
}
return true;
Expand Down
34 changes: 28 additions & 6 deletions src/vnsw/agent/pkt/flow_table.cc
Expand Up @@ -11,6 +11,7 @@
#include <sandesh/sandesh_types.h>
#include <sandesh/sandesh.h>
#include <sandesh/sandesh_trace.h>
#include <net/address_util.h>
#include <pkt/flow_table.h>
#include <vrouter/flow_stats/flow_stats_collector.h>
#include <vrouter/ksync/ksync_init.h>
Expand Down Expand Up @@ -174,7 +175,7 @@ uint32_t FlowEntry::MatchAcl(const PacketHeader &hdr,
}

// PASS default GW traffic, if it is ICMP or DNS
if ((hdr.protocol == IPPROTO_ICMP ||
if ((hdr.protocol == IPPROTO_ICMP || hdr.protocol == IPPROTO_ICMPV6 ||
(hdr.protocol == IPPROTO_UDP &&
(hdr.src_port == DNS_SERVER_PORT ||
hdr.dst_port == DNS_SERVER_PORT))) &&
Expand Down Expand Up @@ -1055,7 +1056,13 @@ void FlowEntry::FillFlowInfo(FlowInfo &info) {
info.set_source_ip(key_.src_addr.to_v4().to_ulong());
info.set_destination_ip(key_.dst_addr.to_v4().to_ulong());
} else {
// TODO : IPV6
uint64_t sip[2], dip[2];
Ip6AddressToU64Array(key_.src_addr.to_v6(), sip, 2);
Ip6AddressToU64Array(key_.dst_addr.to_v6(), dip, 2);
info.set_sip_upper(sip[0]);
info.set_sip_lower(sip[1]);
info.set_dip_upper(dip[0]);
info.set_dip_lower(dip[1]);
info.set_source_ip(0);
info.set_destination_ip(0);
}
Expand Down Expand Up @@ -1247,10 +1254,6 @@ void FlowEntry::SetAclFlowSandeshData(const AclDBEntry *acl,

bool FlowEntry::SetRpfNH(const AgentRoute *rt) {
const NextHop *nh = rt->GetActiveNextHop();
if (key_.family != Address::INET) {
//TODO:IPV6
return false;
}
if (nh->GetType() == NextHop::COMPOSITE &&
!is_flags_set(FlowEntry::LocalFlow) &&
is_flags_set(FlowEntry::IngressDir)) {
Expand Down Expand Up @@ -2238,6 +2241,15 @@ void FlowTable::VrfFlowHandlerState::Register(VrfEntry *vrf) {
(inet_table->Register(boost::bind(&RouteFlowUpdate::Notify,
inet4_unicast_update_, _1, _2)));

// Register to the Inet6 Unicast Table
InetUnicastAgentRouteTable *inet6_table =
static_cast<InetUnicastAgentRouteTable *>
(vrf->GetInet6UnicastRouteTable());
inet6_unicast_update_ = new InetRouteFlowUpdate(inet6_table);
inet6_unicast_update_->set_dblistener_id
(inet6_table->Register(boost::bind(&RouteFlowUpdate::Notify,
inet6_unicast_update_, _1, _2)));

// Register to the Bridge Unicast Table
BridgeAgentRouteTable *bridge_table =
static_cast<BridgeAgentRouteTable *>
Expand All @@ -2249,6 +2261,8 @@ void FlowTable::VrfFlowHandlerState::Register(VrfEntry *vrf) {
LOG(DEBUG, "ROUTE-FLOW-UPDATE"
<< " Inet : " << inet4_unicast_update_
<< " Listener : " << inet4_unicast_update_->dblistener_id()
<< " Inet6 : " << inet6_unicast_update_
<< " Listener : " << inet6_unicast_update_->dblistener_id()
<< " Bridge : " << bridge_update_
<< " Listener : " << bridge_update_->dblistener_id());
}
Expand All @@ -2268,6 +2282,14 @@ void FlowTable::VrfFlowHandlerState::Unregister(VrfEntry *vrf) {
inet4_unicast_update_));
inet4_unicast_update_->set_walk_id(id);

DBTableWalker *walker6 = agent->db()->GetWalker();
id = walker6->WalkTable(vrf->GetInet6UnicastRouteTable(), NULL,
boost::bind(&RouteFlowUpdate::DeleteState,
_1, _2, inet6_unicast_update_),
boost::bind(&RouteFlowUpdate::WalkDone, _1,
inet6_unicast_update_));
inet6_unicast_update_->set_walk_id(id);

DBTableWalker *bridge_walker = agent->db()->GetWalker();
id = bridge_walker->WalkTable(vrf->GetBridgeRouteTable(), NULL,
boost::bind(&RouteFlowUpdate::DeleteState,
Expand Down
1 change: 1 addition & 0 deletions src/vnsw/agent/pkt/flow_table.h
Expand Up @@ -616,6 +616,7 @@ class FlowTable {
void Unregister(VrfEntry *vrf);

InetRouteFlowUpdate *inet4_unicast_update_;
InetRouteFlowUpdate *inet6_unicast_update_;
BridgeEntryFlowUpdate *bridge_update_;
};
struct RouteFlowHandlerState : public DBState {
Expand Down
8 changes: 8 additions & 0 deletions src/vnsw/agent/pkt/pkt.sandesh
Expand Up @@ -193,6 +193,10 @@ struct FlowInfo {
32: bool l3_flow;
33: string smac;
34: string dmac;
35: optional u64 sip_upper;
36: optional u64 sip_lower;
37: optional u64 dip_upper;
38: optional u64 dip_lower;
}

traceobject sandesh FlowTrace {
Expand All @@ -208,6 +212,10 @@ trace sandesh FlowDetailErr {
5: u32 dip;
6: string error;
7: bool l3_flow;
8: u64 sip_upper;
9: u64 sip_lower;
10: u64 dip_upper;
11: u64 dip_lower;
}

trace sandesh FlowErr {
Expand Down

0 comments on commit 113cbc7

Please sign in to comment.