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