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