OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
flow_handler.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 #include <base/address.h>
5 #include <base/address_util.h>
6 #include "pkt/proto.h"
7 #include "pkt/proto_handler.h"
8 #include "pkt/pkt_init.h"
9 #include "pkt/pkt_handler.h"
10 #include "pkt/flow_table.h"
11 #include "pkt/flow_proto.h"
12 #include "pkt/flow_handler.h"
13 
15 
16 static const VmEntry *InterfaceToVm(const Interface *intf) {
17  if (intf->type() != Interface::VM_INTERFACE)
18  return NULL;
19 
20  const VmInterface *vm_port = static_cast<const VmInterface *>(intf);
21  return vm_port->vm();
22 }
23 
24 // Compute L2/L3 forwarding mode for pacekt.
25 // Forwarding mode is L3 if,
26 // - Packet uses L3 label
27 // - Packet uses L2 Label and DMAC hits a route with L2-Receive NH
28 // Else forwarding mode is L2
30  const Interface *intf =
31  agent_->interface_table()->FindInterface(pkt_info_->agent_hdr.ifindex);
32  // here return true/false does not make any difference as flow processing
33  // will be aborted due to invalid interface in subsequent processing.
34  if (intf == NULL) {
35  return false;
36  }
37  if (intf->type() == Interface::INET) {
38  return true;
39  }
40 
41  if (intf->type() == Interface::VM_INTERFACE) {
42  const VmInterface *vm_intf =
43  static_cast<const VmInterface *>(intf);
44  if (vm_intf == agent_->vhost_interface()) {
45  return true;
46  }
47  }
48 
49  if (pkt_info_->l3_label) {
50  return true;
51  }
52 
53  VrfTable *table = static_cast<VrfTable *>(agent_->vrf_table());
54  VrfEntry *vrf = table->FindVrfFromId(pkt_info_->agent_hdr.vrf);
55  if (vrf == NULL) {
56  return false;
57  }
58  BridgeAgentRouteTable *l2_table = static_cast<BridgeAgentRouteTable *>
59  (vrf->GetBridgeRouteTable());
60  AgentRoute *rt = static_cast<AgentRoute *>
61  (l2_table->FindRouteNoLock(pkt_info_->dmac));
62  if (rt == NULL) {
63  return false;
64  }
65 
66  const NextHop *nh = rt->GetActiveNextHop();
67  if (nh == NULL) {
68  return false;
69  }
70 
71  if (nh->GetType() == NextHop::L2_RECEIVE) {
72  return true;
73  }
74  return false;
75 }
76 
78  PktControlInfo in;
79  PktControlInfo out;
82  std::unique_ptr<FlowTaskMsg> ipc;
83  bool allow_reentrant = true;
84  if (pkt_info_->type == PktType::INVALID) {
85  info.SetPktInfo(pkt_info_);
86  info.l3_flow = IsL3ModeFlow();
87  } else if (pkt_info_->type == PktType::MESSAGE) {
88  // we don't allow reentrancy to different partition if it is
89  // a reevaluation for an existing flow which will only exist
90  // in this partition
91  allow_reentrant = false;
92  ipc = std::unique_ptr<FlowTaskMsg>(static_cast<FlowTaskMsg *>(pkt_info_->ipc));
93  pkt_info_->ipc = NULL;
94  FlowEntry *fe = ipc->fe_ptr.get();
95  // take lock on flow entry before accessing it, since we need to read
96  // forward flow only take lock only on forward flow
97  tbb::mutex::scoped_lock lock1(fe->mutex());
98  assert(flow_table_index_ == fe->flow_table()->table_index());
99 
100  if (fe->deleted() || fe->is_flags_set(FlowEntry::ShortFlow)) {
101  return true;
102  }
103 
104  // We dont support revaluation of linklocal flows
106  return true;
107  }
108 
109  info.flow_entry = fe;
110  pkt_info_->agent_hdr.cmd = AGENT_TRAP_FLOW_MISS;
111  pkt_info_->agent_hdr.cmd_param = fe->flow_handle();
112  pkt_info_->agent_hdr.ifindex = fe->data().if_index_info;
113  pkt_info_->tunnel = fe->data().tunnel_info;
114  pkt_info_->agent_hdr.nh = fe->key().nh;
115  pkt_info_->agent_hdr.vrf = fe->data().vrf;
116  pkt_info_->family =
117  fe->key().src_addr.is_v4() ? Address::INET : Address::INET6;
118  pkt_info_->smac = fe->data().smac;
119  pkt_info_->dmac = fe->data().dmac;
120  pkt_info_->ip_saddr = fe->key().src_addr;
121  pkt_info_->ip_daddr = fe->key().dst_addr;
122  pkt_info_->ip_proto = fe->key().protocol;
123  pkt_info_->sport = fe->key().src_port;
124  pkt_info_->dport = fe->key().dst_port;
126  pkt_info_->vrf = fe->data().vrf;
127  pkt_info_->ttl = fe->data().ttl;
128  info.l3_flow = fe->l3_flow();
129  info.out_component_nh_idx = fe->data().component_nh_idx;
130  }
131 
132  if (info.Process(pkt_info_.get(), &in, &out) == false) {
133  info.short_flow = true;
134  }
135 
136  // Flows that change port-numbers are always processed in thread-0.
137  // Identify flows that change port and enqueue to thread-0
138  if (allow_reentrant && ((pkt_info_->sport != info.nat_sport) ||
139  (pkt_info_->dport != info.nat_dport))) {
140  if ((info.nat_sport != 0 || info.nat_dport != 0)) {
142  // Enqueue flow evaluation to
143  // FlowTable::kPortNatFlowTableInstance instance.
146  return true;
147  }
148  }
149  }
150 
151  if (in.intf_ && ((in.intf_->type() != Interface::VM_INTERFACE) &&
152  (in.intf_->type() != Interface::INET))) {
153  in.intf_ = NULL;
154  }
155 
156  if (in.intf_ && out.intf_) {
157  info.local_flow = true;
158  }
159 
160  if (in.intf_) {
161  in.vm_ = InterfaceToVm(in.intf_);
162  }
163 
164  if (out.intf_) {
165  out.vm_ = InterfaceToVm(out.intf_);
166  }
167 
168  info.Add(pkt_info_.get(), &in, &out);
169  return true;
170 }
void SetPktInfo(boost::shared_ptr< PktInfo > info)
IpAddress src_addr
Definition: flow_entry.h:213
Type type() const
Definition: interface.h:112
Definition: vrf.h:86
Definition: vrf.h:268
FlowTable * flow_table() const
Definition: flow_entry.h:597
uint32_t component_nh_idx
Definition: flow_entry.h:318
IpAddress dst_addr
Definition: flow_entry.h:214
static const uint32_t kPortNatFlowTableInstance
Definition: flow_table.h:154
const Interface * vhost_interface() const
Definition: agent.h:935
MacAddress dmac
Definition: flow_entry.h:293
Definition: vm.h:32
static const VmEntry * InterfaceToVm(const Interface *intf)
Definition: flow_handler.cc:16
InterfaceTable * interface_table() const
Definition: agent.h:465
uint16_t table_index() const
Definition: flow_table.h:198
uint8_t protocol
Definition: flow_entry.h:215
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
Definition: sandesh_trace.h:18
Type GetType() const
Definition: nexthop.h:405
Base class for all Route entries in agent.
Definition: agent_route.h:224
boost::shared_ptr< PktInfo > pkt_info_
Definition: proto_handler.h:92
BridgeRouteEntry * FindRouteNoLock(const MacAddress &mac)
Definition: bridge_route.cc:77
const FlowKey & key() const
Definition: flow_entry.h:594
FlowTable * GetTable(uint16_t index) const
Definition: flow_proto.cc:261
VrfEntry * FindVrfFromId(size_t index)
Definition: vrf.cc:884
bool is_flags_set(const FlowEntryFlags &flags) const
Definition: flow_entry.h:610
FlowProto * flow_proto_
Definition: flow_handler.h:38
uint32_t vrf
Definition: flow_entry.h:315
const NextHop * GetActiveNextHop() const
Definition: agent_route.cc:881
bool IsL3ModeFlow() const
Definition: flow_handler.cc:29
MacAddress smac
Definition: flow_entry.h:292
AgentRouteTable * GetBridgeRouteTable() const
Definition: vrf.cc:334
uint32_t if_index_info
Definition: flow_entry.h:337
tbb::mutex & mutex()
Definition: flow_entry.h:650
Agent * agent_
Definition: proto_handler.h:91
VrfTable * vrf_table() const
Definition: agent.h:485
uint16_t src_port
Definition: flow_entry.h:216
bool l3_flow() const
Definition: flow_entry.h:598
const Interface * intf_
Definition: pkt_flow_info.h:27
SandeshTraceBufferPtr PktFlowTraceBuf
uint32_t flow_handle() const
Definition: flow_entry.h:600
TunnelInfo tunnel_info
Definition: flow_entry.h:338
uint16_t dst_port
Definition: flow_entry.h:217
uint16_t flow_table_index_
Definition: flow_handler.h:39
const Interface * FindInterface(size_t index) const
Definition: interface.cc:323
const VmEntry * vm_
Definition: pkt_flow_info.h:30
FlowData & data()
Definition: flow_entry.h:595
bool deleted()
Definition: flow_entry.h:680
bool EnqueueReentrant(boost::shared_ptr< PktInfo > msg, uint8_t table_index)
Definition: flow_proto.cc:669
uint32_t nh
Definition: flow_entry.h:212
uint32_t ttl
Definition: flow_entry.h:322
const VmEntry * vm() const
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
Definition: sandesh_trace.h:46