OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
proto_handler.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <stdint.h>
6 #include "base/os.h"
7 #include "vr_defs.h"
8 #include "pkt/proto_handler.h"
9 #include "pkt/pkt_init.h"
10 #include "pkt/packet_buffer.h"
11 
13 
14 ProtoHandler::ProtoHandler(Agent *agent, boost::shared_ptr<PktInfo> info,
15  boost::asio::io_context &io)
16  : agent_(agent), pkt_info_(info), io_(io) {}
17 
19 }
20 
21 uint32_t ProtoHandler::EncapHeaderLen() const {
22  return agent_->pkt()->pkt_handler()->EncapHeaderLen();
23 }
24 
25 // send packet to the pkt0 interface
26 void ProtoHandler::Send(uint32_t itf, uint32_t vrf, uint16_t cmd,
28  Send(itf, vrf, cmd, 0, 0, mod);
29 }
30 
31 void ProtoHandler::Send(uint32_t itf, uint32_t vrf, uint16_t cmd,
32  uint32_t param1, uint32_t param2,
34  // If pkt_info_->pkt is non-NULL, pkt is freed in destructor of pkt_info_
35  if (agent_->pkt()->pkt_handler() == NULL) {
36  return;
37  }
38 
39  AgentHdr hdr(itf, vrf, cmd, param1, param2);
40  agent_->pkt()->pkt_handler()->Send(hdr, pkt_info_->packet_buffer_ptr());
41 }
42 
43 int ProtoHandler::EthHdr(char *buff, uint16_t len, const MacAddress &src,
44  const MacAddress &dest, const uint16_t proto,
45  uint16_t vlan_id) {
46  struct ether_header *eth = (struct ether_header *)buff;
47  uint16_t encap_len = sizeof(struct ether_header);
48 
49  if (vlan_id != VmInterface::kInvalidVlanId) {
50  encap_len += 4;
51  }
52 
53  if (len < encap_len) {
54  return 0;
55  }
56 
57  dest.ToArray(eth->ether_dhost, sizeof(eth->ether_dhost));
58  src.ToArray(eth->ether_shost, sizeof(eth->ether_shost));
59 
60  uint16_t *ptr = (uint16_t *) (buff + ETHER_ADDR_LEN * 2);
61  if (vlan_id != VmInterface::kInvalidVlanId) {
62  *ptr = htons(ETHERTYPE_VLAN);
63  ptr++;
64  *ptr = htons(vlan_id & 0xFFF);
65  ptr++;
66  }
67 
68  *ptr = htons(proto);
69  return encap_len;
70 }
71 
72 int ProtoHandler::EthHdr(const MacAddress &src, const MacAddress &dest,
73  const uint16_t proto) {
74  return EthHdr((char *)pkt_info_->eth, sizeof(struct ether_header), src,
75  dest, proto, VmInterface::kInvalidVlanId);
76 }
77 
78 int ProtoHandler::EthHdr(char *buff, uint16_t len, const Interface *intrface,
79  const MacAddress &src, const MacAddress &dest,
80  const uint16_t proto) {
81  uint16_t vlan_id = VmInterface::kInvalidVlanId;
82  if (intrface && intrface->type() == Interface::VM_INTERFACE &&
83  !(agent_->tsn_enabled())) {
84  vlan_id = static_cast<const VmInterface *>(intrface)->tx_vlan_id();
85  }
86 
87  return EthHdr(buff, len, src, dest, proto, vlan_id);
88 }
89 
90 int ProtoHandler::EthHdr(char *buff, uint16_t len, uint32_t ifindex,
91  const MacAddress &src, const MacAddress &dest,
92  const uint16_t proto) {
93  const Interface *intf = agent()->interface_table()->FindInterface(ifindex);
94  return EthHdr(buff, len, intf, src, dest, proto);
95 }
96 
97 void ProtoHandler::VlanHdr(uint8_t *ptr, uint16_t tci) {
98  vlanhdr *vlan = reinterpret_cast<vlanhdr *>(ptr);
99  vlan->tpid = htons(0x8100);
100  vlan->tci = htons(tci);
101  vlan += 1;
102  vlan->tpid = htons(0x800);
103  return;
104 }
105 
106 uint16_t ProtoHandler::IpHdr(char *buff, uint16_t buf_len, uint16_t len,
107  in_addr_t src, in_addr_t dest, uint8_t protocol,
108  uint16_t id, uint8_t ttl) {
109  struct ip *ip = (struct ip *)buff;
110  if (buf_len < sizeof(struct ip))
111  return 0;
112 
113  ip->ip_hl = 5;
114  ip->ip_v = 4;
115  ip->ip_tos = 0;
116  ip->ip_len = htons(len);
117  ip->ip_id = htons(id);
118  ip->ip_off = 0;
119  ip->ip_ttl = ttl;
120  ip->ip_p = protocol;
121  ip->ip_sum = 0;
122  ip->ip_src.s_addr = src;
123  ip->ip_dst.s_addr = dest;
124 
125  ip->ip_sum = Csum((uint16_t *)ip, ip->ip_hl * 4, 0);
126  return sizeof(struct ip);
127 }
128 
129 void ProtoHandler::IpHdr(uint16_t len, in_addr_t src, in_addr_t dest,
130  uint8_t protocol, uint16_t id, uint8_t ttl) {
131 
132  IpHdr((char *)pkt_info_->ip, sizeof(struct ip), len,
133  src, dest, protocol, id, ttl);
134 }
135 
136 void ProtoHandler::Ip6Hdr(ip6_hdr *ip, uint16_t plen, uint8_t next_header,
137  uint8_t hlim, uint8_t *src, uint8_t *dest) {
138  ip->ip6_flow = htonl(0x60000000); // version 6, TC and Flow set to 0
139  ip->ip6_plen = htons(plen);
140  ip->ip6_nxt = next_header;
141  ip->ip6_hlim= hlim;
142  memcpy(ip->ip6_src.s6_addr, src, 16);
143  memcpy(ip->ip6_dst.s6_addr, dest, 16);
144 }
145 
146 void ProtoHandler::FillUdpHdr(udphdr *udp, uint16_t len,
147  uint16_t src_port, uint16_t dest_port) {
148  udp->uh_sport = htons(src_port);
149  udp->uh_dport = htons(dest_port);
150  udp->uh_ulen = htons(len);
151  udp->uh_sum = 0;
152 }
153 
154 uint16_t ProtoHandler::UdpHdr(udphdr *udp, uint16_t buf_len, uint16_t len,
155  in_addr_t src, uint16_t src_port, in_addr_t dest,
156  uint16_t dest_port) {
157  if (buf_len < sizeof(udphdr))
158  return 0;
159 
160  FillUdpHdr(udp, len, src_port, dest_port);
161 #ifdef VNSW_AGENT_UDP_CSUM
162  udp->uh_sum = UdpCsum(src, dest, len, udp);
163 #endif
164 
165  return sizeof(udphdr);
166 }
167 
168 void ProtoHandler::UdpHdr(uint16_t len, in_addr_t src, uint16_t src_port,
169  in_addr_t dest, uint16_t dest_port) {
170  UdpHdr(pkt_info_->transp.udp, sizeof(udphdr), len, src, src_port,
171  dest, dest_port);
172 }
173 
174 uint16_t ProtoHandler::IcmpHdr(char *buff, uint16_t buf_len, uint8_t type,
175  uint8_t code, uint16_t word1, uint16_t word2) {
176  struct icmp *hdr = ((struct icmp *)buff);
177  if (buf_len < sizeof(hdr))
178  return 0;
179 
180  memset(hdr, 0, sizeof(struct icmp));
181 
182  hdr->icmp_type = type;
183  hdr->icmp_code = code;
184  if(type != ICMP_UNREACH) {
185  LOG(ERROR,
186  "Error type != ICMP_UNREACH. BackTrace: " << AgentBackTrace(1));
187  return 0;
188  }
189  hdr->icmp_nextmtu = htons(word2);
190  hdr->icmp_cksum = 0;
191  if (type == ICMP_UNREACH)
192  return ICMP_UNREACH_HDR_LEN;
193  return 0;
194 }
195 
196 void ProtoHandler::IcmpChecksum(char *buff, uint16_t buf_len) {
197  struct icmp *hdr = ((struct icmp *)buff);
198  hdr->icmp_cksum = Csum((uint16_t *)buff, buf_len, 0);
199 }
200 
201 void ProtoHandler::IgmpChecksum(char *buff, uint16_t buf_len) {
202  struct igmp *hdr = ((struct igmp *)buff);
203  hdr->igmp_cksum = Csum((uint16_t *)buff, buf_len, 0);
204 }
205 
206 void ProtoHandler::UdpHdr(udphdr *udp ,uint16_t len, const uint8_t *src,
207  uint16_t src_port, const uint8_t *dest,
208  uint16_t dest_port, uint8_t next_hdr) {
209  FillUdpHdr(udp, len, src_port, dest_port);
210  pkt_info_->transp.udp->uh_sum = Ipv6Csum(src, dest, len, next_hdr,
211  (uint16_t *)pkt_info_->transp.udp);
212 }
213 
214 void ProtoHandler::UdpHdr(uint16_t len, const uint8_t *src, uint16_t src_port,
215  const uint8_t *dest, uint16_t dest_port,
216  uint8_t next_hdr) {
217  FillUdpHdr(pkt_info_->transp.udp, len, src_port, dest_port);
218  pkt_info_->transp.udp->uh_sum = Ipv6Csum(src, dest, len, next_hdr,
219  (uint16_t *)pkt_info_->transp.udp);
220 }
221 
222 uint32_t ProtoHandler::Sum(uint16_t *ptr, std::size_t len, uint32_t sum) const {
223  while (len > 1) {
224  sum += *ptr++;
225  len -= 2;
226  if (sum & 0x80000000)
227  sum = (sum & 0xFFFF) + (sum >> 16);
228  }
229 
230  if (len > 0)
231  sum += *(uint8_t *)ptr;
232 
233  return sum;
234 }
235 
236 uint16_t ProtoHandler::Csum(uint16_t *ptr, std::size_t len, uint32_t sum) const{
237  sum = Sum(ptr, len, sum);
238 
239  while (sum >> 16)
240  sum = (sum & 0xFFFF) + (sum >> 16);
241 
242  return ~sum;
243 }
244 
245 uint16_t ProtoHandler::UdpCsum(in_addr_t src, in_addr_t dest,
246  std::size_t len, udphdr *udp) const {
247  uint32_t sum = 0;
248  PseudoUdpHdr phdr(src, dest, IPPROTO_UDP, htons(len));
249  sum = Sum((uint16_t *)&phdr, sizeof(PseudoUdpHdr), sum);
250  return Csum((uint16_t *)udp, len, sum);
251 }
252 
253 uint16_t ProtoHandler::Ipv6Csum(const uint8_t *src, const uint8_t *dest,
254  uint16_t plen, uint8_t next_hdr,
255  uint16_t *hdr) const {
256  uint32_t len = htonl((uint32_t)plen);
257  uint32_t next = htonl((uint32_t)next_hdr);
258 
259  uint32_t pseudo = 0;
260  pseudo = Sum((uint16_t *)src, 16, 0);
261  pseudo = Sum((uint16_t *)dest, 16, pseudo);
262  pseudo = Sum((uint16_t *)&len, 4, pseudo);
263  pseudo = Sum((uint16_t *)&next, 4, pseudo);
264  return Csum(hdr, plen, pseudo);
265 }
266 
267 uint16_t ProtoHandler::Icmpv6Csum(const uint8_t *src, const uint8_t *dest,
268  icmp6_hdr *icmp, uint16_t plen) const {
269  return Ipv6Csum(src, dest, plen, IPPROTO_ICMPV6, (uint16_t *)icmp);
270 }
271 
Type type() const
Definition: interface.h:112
bool tsn_enabled() const
Definition: agent.h:1162
uint32_t EncapHeaderLen() const
bool ToArray(u_int8_t *p, size_t s) const
Definition: mac_address.cc:93
ProtoHandler(Agent *agent, boost::shared_ptr< PktInfo > info, boost::asio::io_context &io)
uint16_t UdpCsum(in_addr_t, in_addr_t, std::size_t, udphdr *) const
uint16_t Ipv6Csum(const uint8_t *src, const uint8_t *dest, uint16_t plen, uint8_t next_hdr, uint16_t *hdr) const
InterfaceTable * interface_table() const
Definition: agent.h:465
uint16_t Csum(uint16_t *, std::size_t, uint32_t) const
Agent * agent() const
Definition: proto_handler.h:80
virtual ~ProtoHandler()
boost::shared_ptr< PktInfo > pkt_info_
Definition: proto_handler.h:92
void IgmpChecksum(char *buff, uint16_t buf_len)
int EthHdr(const MacAddress &src, const MacAddress &dest, const uint16_t proto)
uint8_t type
Definition: load_balance.h:109
static const uint32_t kInvalidVlanId
Definition: vm_interface.h:360
Definition: agent.h:358
void Send(uint32_t itf, uint32_t vrf, uint16_t, PktHandler::PktModuleName)
PktHandler * pkt_handler() const
Definition: pkt_init.h:31
void VlanHdr(uint8_t *ptr, uint16_t tci)
void Send(const AgentHdr &hdr, const PacketBufferPtr &buff)
Definition: pkt_handler.cc:94
void Ip6Hdr(ip6_hdr *ip, uint16_t plen, uint8_t next_header, uint8_t hlim, uint8_t *src, uint8_t *dest)
Agent * agent_
Definition: proto_handler.h:91
uint16_t tpid
Definition: proto_handler.h:22
std::string AgentBackTrace(int skip=1)
Definition: agent.cc:1187
void IcmpChecksum(char *buff, uint16_t buf_len)
#define ICMP_UNREACH_HDR_LEN
Definition: pkt_handler.h:51
void UdpHdr(uint16_t len, in_addr_t src, uint16_t src_port, in_addr_t dest, uint16_t dest_port)
const Interface * FindInterface(size_t index) const
Definition: interface.cc:323
#define LOG(_Level, _Msg)
Definition: logging.h:33
void FillUdpHdr(udphdr *udp, uint16_t len, uint16_t src_port, uint16_t dest_port)
uint32_t Sum(uint16_t *, std::size_t, uint32_t) const
uint32_t EncapHeaderLen() const
Definition: pkt_handler.cc:89
PktModule * pkt() const
Definition: agent.cc:965
uint16_t IcmpHdr(char *buff, uint16_t buf_len, uint8_t type, uint8_t code, uint16_t word1, uint16_t word2)
uint16_t Icmpv6Csum(const uint8_t *src, const uint8_t *dest, icmp6_hdr *icmp, uint16_t plen) const
uint16_t tci
Definition: proto_handler.h:23
void IpHdr(uint16_t len, in_addr_t src, in_addr_t dest, uint8_t protocol, uint16_t id, uint8_t ttl)