Line data Source code
1 : /*
2 : * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <cmn/agent_cmn.h>
6 : #include <init/agent_init.h>
7 : #include <pkt/pkt_init.h>
8 : #include <pkt/pkt_handler.h>
9 : #include <services/bfd_proto.h>
10 : #include "mac_learning/mac_learning_proto.h"
11 :
12 2 : BfdHandler::BfdHandler(Agent *agent, boost::shared_ptr<PktInfo> info,
13 2 : boost::asio::io_context &io)
14 2 : : ProtoHandler(agent, info, io) {
15 2 : }
16 :
17 2 : BfdHandler::~BfdHandler() {
18 2 : }
19 :
20 0 : bool BfdHandler::HandleReceive() {
21 0 : BfdProto *bfd_proto = agent()->GetBfdProto();
22 0 : uint8_t len = ntohs(pkt_info_->transp.udp->len) - 8;
23 0 : uint8_t *data = new uint8_t[len];
24 0 : memcpy(data, pkt_info_->data, len);
25 0 : boost::asio::const_buffer buffer(boost::asio::buffer(data, len));
26 :
27 0 : boost::system::error_code ec;
28 0 : boost::asio::ip::udp::endpoint local_endpoint(pkt_info_->ip_daddr,
29 0 : pkt_info_->dport);
30 0 : boost::asio::ip::udp::endpoint remote_endpoint(pkt_info_->ip_saddr,
31 0 : pkt_info_->sport);
32 : // thread safe!
33 0 : bfd_proto->HandleReceiveSafe(
34 : buffer, local_endpoint, remote_endpoint,
35 0 : BFD::SessionIndex(GetInterfaceIndex()),
36 : len, ec);
37 0 : return true;
38 : }
39 :
40 0 : bool BfdHandler::Run() {
41 : Interface *itf =
42 0 : agent()->interface_table()->FindInterface(GetInterfaceIndex());
43 0 : if (itf == NULL) {
44 0 : return true;
45 : }
46 :
47 0 : return HandleReceive();
48 : }
49 :
50 0 : void BfdHandler::SendPacket(
51 : const boost::asio::ip::udp::endpoint &local_endpoint,
52 : const boost::asio::ip::udp::endpoint &remote_endpoint,
53 : uint32_t interface_id, const boost::asio::mutable_buffer &packet,
54 : int packet_length) {
55 :
56 : Interface *intrface =
57 0 : agent()->interface_table()->FindInterface(interface_id);
58 0 : if (!intrface || intrface->type() != Interface::VM_INTERFACE)
59 0 : return;
60 :
61 0 : if (pkt_info_->packet_buffer() == NULL) {
62 0 : pkt_info_->AllocPacketBuffer(agent(), PktHandler::BFD,
63 : BFD_TX_BUFF_LEN, 0);
64 : }
65 :
66 0 : uint16_t buf_len = pkt_info_->packet_buffer()->data_len();
67 0 : char *ptr = (char *)pkt_info_->packet_buffer()->data();
68 0 : memset(ptr, 0, buf_len);
69 0 : pkt_info_->eth = (struct ether_header *)ptr;
70 :
71 0 : VmInterface *vm_interface = static_cast<VmInterface *>(intrface);
72 0 : bool is_v4 = local_endpoint.address().is_v4();
73 0 : uint16_t len = 0;
74 :
75 0 : uint8_t *data = boost::asio::buffer_cast<uint8_t *>(packet);
76 0 : uint16_t eth_proto = is_v4 ? ETHERTYPE_IP : ETHERTYPE_IPV6;
77 : MacAddress mac = agent()->mac_learning_proto()->
78 : GetMacIpLearningTable()->GetPairedMacAddress(
79 0 : vm_interface->vrf()?
80 0 : vm_interface->vrf()->vrf_id():
81 : VrfEntry::kInvalidIndex,
82 0 : remote_endpoint.address());
83 :
84 0 : if (mac == MacAddress()) {
85 0 : mac = vm_interface->vm_mac();
86 : }
87 :
88 0 : len += EthHdr(ptr + len, buf_len - len,
89 0 : agent()->vrrp_mac(),
90 : mac,
91 0 : eth_proto, vm_interface->tx_vlan_id());
92 :
93 0 : if (is_v4) {
94 0 : uint16_t ip_len = sizeof(struct ip) + sizeof(udphdr) + packet_length;
95 0 : len += IpHdr(ptr + len, buf_len - len, ip_len,
96 0 : htonl(local_endpoint.address().to_v4().to_ulong()),
97 0 : htonl(remote_endpoint.address().to_v4().to_ulong()),
98 : IPPROTO_UDP, 0, 255);
99 0 : memcpy(ptr + len + sizeof(udphdr), data, packet_length);
100 0 : len += UdpHdr((udphdr *)(ptr + len), buf_len - len,
101 0 : sizeof(udphdr) + packet_length,
102 0 : htonl(local_endpoint.address().to_v4().to_ulong()),
103 0 : local_endpoint.port(),
104 0 : htonl(remote_endpoint.address().to_v4().to_ulong()),
105 0 : remote_endpoint.port());
106 : } else {
107 0 : pkt_info_->ip6 = (struct ip6_hdr *)(ptr + len);
108 0 : Ip6Hdr((ip6_hdr *)(ptr + len),
109 0 : sizeof(udphdr) + packet_length,
110 : IPPROTO_UDP, 64,
111 0 : local_endpoint.address().to_v6().to_bytes().data(),
112 0 : remote_endpoint.address().to_v6().to_bytes().data());
113 0 : len += sizeof(ip6_hdr);
114 0 : memcpy(ptr + len + sizeof(udphdr), data, packet_length);
115 0 : pkt_info_->transp.udp = (struct udphdr *)(ptr + len);
116 0 : UdpHdr((udphdr *)(ptr + len), sizeof(udphdr) + packet_length,
117 0 : local_endpoint.address().to_v6().to_bytes().data(),
118 0 : local_endpoint.port(),
119 0 : remote_endpoint.address().to_v6().to_bytes().data(),
120 0 : remote_endpoint.port(), IPPROTO_UDP);
121 0 : len += sizeof(udphdr);
122 : }
123 :
124 0 : len += packet_length;
125 :
126 0 : pkt_info_->set_len(len);
127 0 : Send(interface_id, vm_interface->vrf_id(),
128 : AgentHdr::TX_SWITCH, PktHandler::BFD);
129 0 : pkt_info_->reset_packet_buffer();
130 0 : const uint8_t *p = boost::asio::buffer_cast<const uint8_t *>(packet);
131 0 : delete[] p;
132 : }
|