Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #ifndef vnsw_agent_pkt_handler_hpp
7 : #define vnsw_agent_pkt_handler_hpp
8 :
9 : #include <net/if.h>
10 : #include <sys/socket.h>
11 : #include <netinet/if_ether.h>
12 : #include <netinet/ip.h>
13 : #include <netinet/ip6.h>
14 : #include <netinet/ip_icmp.h>
15 : #include <netinet/igmp.h>
16 :
17 : #include <boost/array.hpp>
18 :
19 : #include <base/address.h>
20 : #include <net/mac_address.h>
21 : #include <oper/mirror_table.h>
22 : #include <oper/nexthop.h>
23 : #include <pkt/pkt_trace.h>
24 : #include <pkt/packet_buffer.h>
25 :
26 : #include "vr_defs.h"
27 :
28 : #define DNS_SERVER_PORT 53
29 : #define DHCP_SERVER_PORT 67
30 : #define DHCP_CLIENT_PORT 68
31 : #define DHCPV6_SERVER_PORT 547
32 : #define DHCPV6_CLIENT_PORT 546
33 : #define BFD_SINGLEHOP_CONTROL_PORT 3784
34 : #define BFD_ECHO_PORT 3785
35 : #define BFD_MULTIHOP_CONTROL_PORT 4784
36 : #define VXLAN_UDP_DEST_PORT 4789
37 : #define IANA_MPLS_OVER_UDP_DEST_PORT 6635
38 : #define MPLS_OVER_UDP_DEST_PORT 51234
39 :
40 : #define IPv4_ALEN 4
41 : #define ARP_TX_BUFF_LEN 128
42 : #define IPC_HDR_LEN (sizeof(struct ether_header) + sizeof(struct agent_hdr))
43 : #define VLAN_PROTOCOL 0x8100
44 : #define DEFAULT_IP_TTL 64
45 : //Ideally VM is one hop away but traffic gets routed so use 2.
46 : #define BGP_SERVICE_TTL_REV_FLOW 2
47 : #define BGP_SERVICE_TTL_FWD_FLOW 255
48 : #define DEFAULT_IP_ID 0
49 : #define VLAN_HDR_LEN 4
50 :
51 : #define ICMP_UNREACH_HDR_LEN 8
52 :
53 : #define ETHERTYPE_QINQ 0x88A8
54 : #define ETHERTYPE_PBB 0x88E7
55 : #define PBB_HEADER_LEN 4
56 :
57 : struct PktInfo;
58 : struct agent_hdr;
59 : class PacketBuffer;
60 : class Proto;
61 : class EcmpLoadBalance;
62 : typedef boost::shared_ptr<PktInfo> PktInfoPtr;
63 :
64 : struct InterTaskMsg {
65 1111 : InterTaskMsg(uint16_t command): cmd(command) {}
66 1111 : virtual ~InterTaskMsg() {}
67 :
68 : uint16_t cmd;
69 : };
70 :
71 : struct GreHdr {
72 : GreHdr() : flags(), protocol() {}
73 : ~GreHdr() {}
74 :
75 : uint16_t flags;
76 : uint16_t protocol;
77 : };
78 :
79 : struct MplsHdr {
80 : MplsHdr() : hdr() {}
81 : ~MplsHdr() {}
82 :
83 : uint32_t hdr;
84 : };
85 :
86 : struct VxlanHdr {
87 : VxlanHdr() : reserved(0), vxlan_id(0) { }
88 7 : VxlanHdr(uint32_t id) : reserved(0), vxlan_id((id) << 8) { }
89 7 : ~VxlanHdr() { }
90 :
91 : uint32_t reserved;
92 : uint32_t vxlan_id;
93 : };
94 :
95 : struct PktType {
96 : enum Type {
97 : INVALID,
98 : ARP,
99 : IP,
100 : UDP,
101 : TCP,
102 : ICMP,
103 : ICMPV6,
104 : NON_IP,
105 : MESSAGE,
106 : SCTP,
107 : IGMP,
108 : };
109 : };
110 :
111 : struct PktStatsType {
112 : enum Type {
113 : PKT_RX,
114 : PKT_RX_ENQUEUE,
115 : PKT_RX_DROP_STATS,
116 : PKT_TX,
117 : PKT_TX_ERROR,
118 : };
119 : };
120 :
121 : struct sctphdr {
122 : u_int16_t th_sport;
123 : u_int16_t th_dport;
124 : u_int32_t vtag;
125 : };
126 :
127 : struct AgentHdr {
128 : // Packet commands between agent and vrouter. The values must be in-sync
129 : // with vrouter/include/vr_defs.h
130 : enum PktCommand {
131 : TX_SWITCH = AGENT_CMD_SWITCH,
132 : TX_ROUTE = AGENT_CMD_ROUTE,
133 : TRAP_ARP = AGENT_TRAP_ARP,
134 : TRAP_L2_PROTOCOL = AGENT_TRAP_L2_PROTOCOLS,
135 : TRAP_NEXTHOP = AGENT_TRAP_NEXTHOP,
136 : TRAP_RESOLVE = AGENT_TRAP_RESOLVE,
137 : TRAP_FLOW_MISS = AGENT_TRAP_FLOW_MISS,
138 : TRAP_L3_PROTOCOLS = AGENT_TRAP_L3_PROTOCOLS,
139 : TRAP_DIAG = AGENT_TRAP_DIAG,
140 : TRAP_UNUSED_1,
141 : TRAP_SOURCE_MISMATCH = AGENT_TRAP_SOURCE_MISMATCH,
142 : TRAP_HANDLE_DF = AGENT_TRAP_HANDLE_DF,
143 : TRAP_TOR_CONTROL_PKT = AGENT_TRAP_TOR_CONTROL_PKT,
144 : TRAP_ZERO_TTL = AGENT_TRAP_ZERO_TTL,
145 : TRAP_ICMP_ERROR = AGENT_TRAP_ICMP_ERROR,
146 : TRAP_FLOW_ACTION_HOLD = AGENT_TRAP_FLOW_ACTION_HOLD,
147 : TRAP_ROUTER_ALERT = AGENT_TRAP_ROUTER_ALERT,
148 : TRAP_MAC_LEARN = AGENT_TRAP_MAC_LEARN,
149 : TRAP_MAC_MOVE = AGENT_TRAP_MAC_MOVE,
150 : TRAP_MAC_IP_LEARNING = AGENT_TRAP_MAC_IP_LEARNING,
151 : TRAP_BFD = AGENT_TRAP_BFD,
152 : INVALID = MAX_AGENT_HDR_COMMANDS
153 : };
154 :
155 : enum PktCommandParams {
156 : PACKET_CMD_PARAM_CTRL = CMD_PARAM_PACKET_CTRL,
157 : PACKET_CMD_PARAM_DIAG = CMD_PARAM_1_DIAG,
158 : MAX_PACKET_CMD_PARAM = MAX_CMD_PARAMS,
159 : };
160 :
161 3701 : AgentHdr() :
162 3701 : ifindex(-1), vrf(-1), cmd(-1), cmd_param(-1), cmd_param_1(-1),
163 3701 : cmd_param_2(0), cmd_param_3(0), cmd_param_4(0), cmd_param_5(0),
164 3701 : nh(-1), flow_index(-1), mtu(0) {}
165 :
166 : AgentHdr(uint32_t ifindex_p, uint32_t vrf_p, uint16_t cmd_p) :
167 : ifindex(ifindex_p), vrf(vrf_p), cmd(cmd_p), cmd_param(-1),
168 : cmd_param_1(-1), cmd_param_2(0), cmd_param_3(0), cmd_param_4(0),
169 : cmd_param_5(0), nh(-1), flow_index(-1), mtu(0) {}
170 :
171 2204 : AgentHdr(uint32_t ifindex_p, uint32_t vrf_p, uint16_t cmd_p,
172 2204 : uint32_t param1, uint32_t param2) :
173 2204 : ifindex(ifindex_p), vrf(vrf_p), cmd(cmd_p), cmd_param(param1),
174 2204 : cmd_param_1(param2), cmd_param_2(0), cmd_param_3(0), cmd_param_4(0),
175 2204 : cmd_param_5(0), nh(-1), flow_index(-1), mtu(0) {}
176 :
177 5980 : ~AgentHdr() {}
178 :
179 : // Fields from agent_hdr
180 : uint32_t ifindex;
181 : uint32_t vrf;
182 : uint16_t cmd;
183 : uint32_t cmd_param;
184 : uint32_t cmd_param_1;
185 : uint32_t cmd_param_2;
186 : uint32_t cmd_param_3;
187 : uint32_t cmd_param_4;
188 : uint8_t cmd_param_5;
189 : uint32_t nh;
190 : uint32_t flow_index;
191 : uint16_t mtu;
192 : };
193 :
194 : // Tunnel header decoded from the MPLSoGRE/MPLSoUDP encapsulated packet on
195 : // fabric. Supports only IPv4 addresses since only IPv4 is supported on fabric
196 : struct TunnelInfo {
197 13623 : TunnelInfo() : type(TunnelType::INVALID) { Reset(); }
198 13623 : ~TunnelInfo() {}
199 :
200 44071 : void Reset() {
201 44071 : type = TunnelType::INVALID;
202 44071 : label = -1;
203 44071 : vxlan_id = -1;
204 44071 : src_port = 0;
205 44071 : ip_saddr = 0;
206 44071 : ip_daddr = 0;
207 44071 : eth = NULL;
208 44071 : ip = NULL;
209 44071 : }
210 :
211 : TunnelType type;
212 : uint32_t label; // Valid only for MPLSoGRE and MPLSoUDP
213 : uint32_t vxlan_id; // Valid only for VXLAN
214 : uint16_t src_port; // Valid only for VXLAN and MPLSoUDP
215 : uint32_t ip_saddr;
216 : uint32_t ip_daddr;
217 : struct ether_header *eth;
218 : struct ip *ip;
219 : };
220 :
221 : // Receive packets from the pkt0 (tap) interface, parse and send the packet to
222 : // appropriate protocol task. Also, protocol tasks can send packets to pkt0
223 : // or to other tasks.
224 : class PktHandler {
225 : public:
226 : typedef boost::function<bool(boost::shared_ptr<PktInfo>)> RcvQueueFunc;
227 : typedef boost::function<void(PktTrace::Pkt &)> PktTraceCallback;
228 :
229 : static const uint32_t kMulticastControlWord = 0;
230 : static const uint32_t kMulticastControlWordSize = 4;
231 : enum PktModuleName {
232 : INVALID,
233 : FLOW,
234 : ARP,
235 : DHCP,
236 : DHCPV6,
237 : DNS,
238 : ICMP,
239 : ICMPV6,
240 : DIAG,
241 : ICMP_ERROR,
242 : ICMPV6_ERROR,
243 : RX_PACKET,
244 : MAC_LEARNING,
245 : BFD,
246 : IGMP,
247 : MAC_IP_LEARNING,
248 : MAX_MODULES
249 : };
250 :
251 : struct PktStats {
252 : uint32_t sent[MAX_MODULES];
253 : uint32_t received[MAX_MODULES];
254 : uint32_t q_threshold_exceeded[MAX_MODULES];
255 : uint32_t dropped;
256 2 : void Reset() {
257 34 : for (int i = 0; i < MAX_MODULES; ++i) {
258 32 : sent[i] = received[i] = q_threshold_exceeded[i] = 0;
259 : }
260 2 : dropped = 0;
261 2 : }
262 2 : PktStats() { Reset(); }
263 : void PktRcvd(PktModuleName mod);
264 : void PktSent(PktModuleName mod);
265 : void PktQThresholdExceeded(PktModuleName mod);
266 : };
267 :
268 : struct PacketBufferEnqueueItem {
269 : const AgentHdr hdr;
270 : const PacketBufferPtr buff;
271 :
272 75 : PacketBufferEnqueueItem(const AgentHdr &h, const PacketBufferPtr &b)
273 75 : : hdr(h), buff(b) {}
274 : };
275 : typedef WorkQueue<boost::shared_ptr<PacketBufferEnqueueItem> >
276 : PktHandlerQueue;
277 :
278 : PktHandler(Agent *, PktModule *pkt_module);
279 : virtual ~PktHandler();
280 :
281 : void Register(PktModuleName type, RcvQueueFunc cb);
282 : void Register(PktModuleName type, Proto *proto);
283 :
284 : void Send(const AgentHdr &hdr, const PacketBufferPtr &buff);
285 :
286 : PktModuleName ParsePacket(const AgentHdr &hdr, PktInfo *pkt_info,
287 : uint8_t *pkt);
288 : PktModuleName ParseBfdDataPacket(const AgentHdr &hdr, PktInfo *pkt_info,
289 : uint8_t *pkt);
290 : int ParseUserPkt(PktInfo *pkt_info, Interface *intf,
291 : PktType::Type &pkt_type, uint8_t *pkt);
292 : bool ProcessPacket(boost::shared_ptr<PacketBufferEnqueueItem> item);
293 : bool ProcessBfdDataPacket(boost::shared_ptr<PacketBufferEnqueueItem> item);
294 : // identify pkt type and send to the registered handler
295 : void HandleRcvPkt(const AgentHdr &hdr, const PacketBufferPtr &buff);
296 : void SendMessage(PktModuleName mod, InterTaskMsg *msg);
297 :
298 : bool IsGwPacket(const Interface *intf, const IpAddress &dst_ip);
299 :
300 12 : const PktStats &GetStats() const { return stats_; }
301 0 : void ClearStats() { stats_.Reset(); }
302 : void PktTraceIterate(PktModuleName mod, PktTraceCallback cb);
303 0 : void PktTraceClear(PktModuleName mod) { pkt_trace_.at(mod).Clear(); }
304 0 : void PktTraceBuffers(PktModuleName mod, uint32_t buffers) {
305 0 : pkt_trace_.at(mod).set_num_buffers(buffers);
306 0 : }
307 0 : uint32_t PktTraceBuffers(PktModuleName mod) const {
308 0 : return pkt_trace_.at(mod).num_buffers();
309 : }
310 0 : uint32_t PktTraceSize(PktModuleName mod) const {
311 0 : return pkt_trace_.at(mod).pkt_trace_size();
312 : }
313 : void AddPktTrace(PktModuleName module, PktTrace::Direction dir,
314 : const PktInfo *pkt);
315 :
316 : uint32_t EncapHeaderLen() const;
317 79 : Agent *agent() const { return agent_; }
318 : PktModule *pkt_module() const { return pkt_module_; }
319 : void Enqueue(PktModuleName module, boost::shared_ptr<PktInfo> pkt_info);
320 : bool IsFlowPacket(PktInfo *pkt_info);
321 : void CalculatePortIP(PktInfo *pkt_info);
322 5 : const PktHandlerQueue *work_queue() const { return &work_queue_; }
323 :
324 : bool IsBFDHealthCheckPacket(const PktInfo *pkt_info,
325 : const Interface *interface);
326 : bool IsSegmentHealthCheckPacket(const PktInfo *pkt_info,
327 : const Interface *interface);
328 :
329 12 : uint64_t GetBfdKaEnqueueCount() {return work_queue_bfd_ka_.NumEnqueues(); }
330 12 : uint64_t GetPktEnqueueCount() {return work_queue_.NumEnqueues(); }
331 :
332 : private:
333 : void PktModuleEnqueue(PktModuleName mod, const AgentHdr &hdr,
334 : boost::shared_ptr<PktInfo> pkt_info, uint8_t *pkt);
335 : int ParseEthernetHeader(PktInfo *pkt_info, uint8_t *pkt);
336 : int ParseMplsHdr(PktInfo *pkt_info, uint8_t *pkt);
337 : int ParseIpPacket(PktInfo *pkt_info, PktType::Type &pkt_type,
338 : uint8_t *ptr);
339 :
340 : int ParseMPLSoGRE(PktInfo *pkt_info, uint8_t *pkt);
341 : int ParseMPLSoUDP(PktInfo *pkt_info, uint8_t *pkt);
342 : int ParseControlWord(PktInfo *pkt_info, uint8_t *pkt,
343 : const MplsLabel *mpls);
344 : int ParseUDPTunnels(PktInfo *pkt_info, uint8_t *pkt);
345 : int ParseVxlan(PktInfo *pkt_info, uint8_t *pkt);
346 : int ParseUdp(PktInfo *pkt_info, uint8_t *pkt);
347 : bool ComputeForwardingMode(PktInfo *pkt_info, const Interface *intf) const;
348 :
349 : void SetOuterIp(PktInfo *pkt_info, uint8_t *pkt);
350 : void SetOuterMac(PktInfo *pkt_info);
351 : bool IgnoreFragmentedPacket(PktInfo *pkt_info);
352 : bool IsDHCPPacket(PktInfo *pkt_info);
353 : bool IsValidInterface(uint32_t ifindex, Interface **interface);
354 : bool IsToRDevice(uint32_t vrf_id, const IpAddress &ip);
355 : bool IsManagedTORPacket(Interface *intf, PktInfo *pkt_info,
356 : PktType::Type &pkt_type, uint8_t *pkt,
357 : bool *pkt_ok);
358 : bool IsFlowPacket(const AgentHdr &agent_hdr);
359 : bool IsDiagPacket(PktInfo *pkt_info);
360 : bool ValidateIpPacket(PktInfo *pkt_info);
361 :
362 : boost::array<Proto *, MAX_MODULES> proto_list_;
363 : Proto *bfd_keepalive_proto_;
364 :
365 : PktStats stats_;
366 : boost::array<PktTrace, MAX_MODULES> pkt_trace_;
367 : DBTableBase::ListenerId iid_;
368 :
369 : Agent *agent_;
370 : PktModule *pkt_module_;
371 : PktHandlerQueue work_queue_;
372 : PktHandlerQueue work_queue_bfd_ka_;
373 : DISALLOW_COPY_AND_ASSIGN(PktHandler);
374 : };
375 :
376 : // Info from the parsed packet
377 : struct PktInfo {
378 : PktHandler::PktModuleName module;
379 : uint8_t *pkt;
380 : uint16_t len;
381 : uint16_t max_pkt_len;
382 :
383 : uint8_t *data;
384 : InterTaskMsg *ipc;
385 :
386 : Address::Family family;
387 : PktType::Type type;
388 : AgentHdr agent_hdr;
389 : uint16_t ether_type;
390 : // Fields extracted for processing in agent
391 : uint32_t vrf;
392 : MacAddress smac;
393 : MacAddress dmac;
394 : IpAddress ip_saddr;
395 : IpAddress ip_daddr;
396 : uint8_t ip_proto;
397 : uint32_t sport;
398 : uint32_t dport;
399 : uint32_t ttl;
400 : uint16_t icmp_chksum;
401 :
402 : MacAddress b_smac;
403 : MacAddress b_dmac;
404 : uint32_t i_sid;
405 :
406 : bool tcp_ack;
407 : TunnelInfo tunnel;
408 : bool l3_label;
409 : bool multicast_label;
410 : bool is_bfd_keepalive; // bfd keepalive packet
411 : bool is_segment_hc_pkt;
412 : VmInterface::FatFlowIgnoreAddressType ignore_address; //fat-flow config
413 : bool same_port_number;
414 : bool is_fat_flow_src_prefix; // indicates fat flow with src prefix
415 : IpAddress ip_ff_src_prefix; // fat flow src prefix
416 : bool is_fat_flow_dst_prefix; // indicates fat flow with dst prefix
417 : IpAddress ip_ff_dst_prefix; // fat flow dst prefix
418 :
419 : // Pointer to different headers in user packet
420 : struct ether_header *eth;
421 : uint32_t *pbb_header;
422 : struct ether_arp *arp;
423 : struct ip *ip;
424 : struct ip6_hdr *ip6;
425 : union {
426 : struct tcphdr *tcp;
427 : struct udphdr *udp;
428 : struct icmp *icmp;
429 : struct icmp6_hdr *icmp6;
430 : struct sctphdr *sctp;
431 : struct igmp *igmp;
432 : } transp;
433 :
434 : PktInfo(Agent *agent, uint32_t buff_len, PktHandler::PktModuleName module,
435 : uint32_t mdata);
436 : PktInfo(const PacketBufferPtr &buff);
437 : PktInfo(const PacketBufferPtr &buff, const AgentHdr &hdr);
438 : PktInfo(PktHandler::PktModuleName module, InterTaskMsg *msg);
439 : virtual ~PktInfo();
440 :
441 : const AgentHdr &GetAgentHdr() const;
442 : void UpdateHeaderPtr();
443 : std::size_t hash(const Agent *agent,
444 : const EcmpLoadBalance &ecmp_has_fields_to_use) const;
445 :
446 8891 : PacketBuffer *packet_buffer() const { return packet_buffer_.get(); }
447 2204 : PacketBufferPtr packet_buffer_ptr() const { return packet_buffer_; }
448 : void AllocPacketBuffer(Agent *agent, uint32_t module, uint16_t len,
449 : uint32_t mdata);
450 : void set_len(uint32_t len);
451 : void reset_packet_buffer();
452 :
453 : uint32_t GetUdpPayloadLength() const;
454 :
455 : private:
456 : PacketBufferPtr packet_buffer_;
457 : };
458 :
459 : #endif
|