-
Notifications
You must be signed in to change notification settings - Fork 390
/
flow_handler.cc
93 lines (82 loc) · 3.18 KB
/
flow_handler.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
* Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
*/
#include <net/address.h>
#include "pkt/proto.h"
#include "pkt/proto_handler.h"
#include "pkt/pkt_init.h"
#include "pkt/pkt_handler.h"
#include "pkt/flow_table.h"
#include "pkt/flow_proto.h"
#include "pkt/flow_handler.h"
SandeshTraceBufferPtr PktFlowTraceBuf(SandeshTraceBufferCreate("FlowHandler", 5000));
static const VmEntry *InterfaceToVm(const Interface *intf) {
if (intf->type() != Interface::VM_INTERFACE)
return NULL;
const VmInterface *vm_port = static_cast<const VmInterface *>(intf);
return vm_port->vm();
}
bool FlowHandler::Run() {
PktControlInfo in;
PktControlInfo out;
PktFlowInfo info(pkt_info_, agent_->pkt()->flow_table());
std::auto_ptr<FlowTaskMsg> ipc;
if (pkt_info_->type == PktType::INVALID) {
// packet parsing is not done, invoke the same here
uint8_t *pkt = pkt_info_->packet_buffer()->data();
PktHandler::PktModuleName mod = agent_->pkt()->pkt_handler()->
ParseFlowPacket(pkt_info_, pkt);
// if packet wasnt for flow module, it would've got enqueued to the
// correct module in the above call. Nothing else to do.
if (mod != PktHandler::FLOW) {
return true;
}
info.SetPktInfo(pkt_info_);
} else if (pkt_info_->type == PktType::MESSAGE) {
ipc = std::auto_ptr<FlowTaskMsg>(static_cast<FlowTaskMsg *>(pkt_info_->ipc));
pkt_info_->ipc = NULL;
FlowEntry *fe = ipc->fe_ptr.get();
assert(fe->set_pending_recompute(false));
if (fe->deleted() || fe->is_flags_set(FlowEntry::ShortFlow)) {
return true;
}
info.flow_entry = fe;
pkt_info_->agent_hdr.cmd = AGENT_TRAP_FLOW_MISS;
pkt_info_->agent_hdr.cmd_param = fe->flow_handle();
pkt_info_->agent_hdr.ifindex = fe->data().if_index_info;
pkt_info_->tunnel = fe->data().tunnel_info;
pkt_info_->agent_hdr.nh = fe->key().nh;
pkt_info_->agent_hdr.vrf = fe->data().vrf;
pkt_info_->family =
fe->key().src_addr.is_v4() ? Address::INET : Address::INET6;
pkt_info_->smac = fe->data().smac;
pkt_info_->dmac = fe->data().dmac;
pkt_info_->ip_saddr = fe->key().src_addr;
pkt_info_->ip_daddr = fe->key().dst_addr;
pkt_info_->ip_proto = fe->key().protocol;
pkt_info_->sport = fe->key().src_port;
pkt_info_->dport = fe->key().dst_port;
pkt_info_->tcp_ack = fe->is_flags_set(FlowEntry::TcpAckFlow);
pkt_info_->vrf = fe->data().vrf;
pkt_info_->l3_forwarding = fe->l3_flow();
info.l3_flow = fe->l3_flow();
}
if (info.Process(pkt_info_.get(), &in, &out) == false) {
info.short_flow = true;
}
if (in.intf_ && ((in.intf_->type() != Interface::VM_INTERFACE) &&
(in.intf_->type() != Interface::INET))) {
in.intf_ = NULL;
}
if (in.intf_ && out.intf_) {
info.local_flow = true;
}
if (in.intf_) {
in.vm_ = InterfaceToVm(in.intf_);
}
if (out.intf_) {
out.vm_ = InterfaceToVm(out.intf_);
}
info.Add(pkt_info_.get(), &in, &out);
return true;
}