OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
linux/pkt0_interface.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <stdio.h>
6 #include <string.h>
7 #include <fcntl.h>
8 #include <assert.h>
9 #include <sys/ioctl.h>
10 #include <sys/socket.h>
11 
12 #include <net/if.h>
13 #include <linux/if_ether.h>
14 #include <linux/if_tun.h>
15 #include <linux/if_packet.h>
16 
17 #include "base/logging.h"
18 #include "cmn/agent_cmn.h"
19 #include "init/agent_param.h"
20 #include "sandesh/sandesh_trace.h"
21 #include "pkt/pkt_types.h"
22 #include "pkt/pkt_init.h"
23 #include "../pkt0_interface.h"
24 
25 #define TUN_INTF_CLONE_DEV "/dev/net/tun"
26 
27 #define TAP_TRACE(obj, ...) \
28 do { \
29  Tap##obj::TraceMsg(PacketTraceBuf, __FILE__, __LINE__, __VA_ARGS__); \
30 } while (false) \
31 
32 
34 
37 
38  if ((tap_fd_ = open(TUN_INTF_CLONE_DEV, O_RDWR)) < 0) {
39  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
40  strerror(errno) << "> opening tap-device"
41  << ". BackTrace: " << AgentBackTrace(1));
42  _Exit(0);
43  }
44 
45  struct ifreq ifr;
46  memset(&ifr, 0, sizeof(ifr));
47  ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
48  strncpy(ifr.ifr_name, name_.c_str(), IF_NAMESIZE-1);
49  if (ioctl(tap_fd_, TUNSETIFF, (void *)&ifr) < 0) {
50  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
51  strerror(errno) << "> creating " << name_
52  << "tap-device. BackTrace: " << AgentBackTrace(1));
53  _Exit(0);
54  }
55 
56  // We dont want the fd to be inherited by child process such as
57  // virsh etc... So, close tap fd on fork.
58  if (fcntl(tap_fd_, F_SETFD, FD_CLOEXEC) < 0) {
59  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
60  strerror(errno) << "> setting fcntl on " << name_
61  << " BackTrace: " << AgentBackTrace(1));
62  _Exit(0);
63  }
64 
65  if (ioctl(tap_fd_, TUNSETPERSIST, 0) < 0) {
66  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
67  strerror(errno) << "> making tap interface non-persistent"
68  << ". BackTrace: " << AgentBackTrace(1));
69  _Exit(0);
70  }
71 
72  memset(&ifr, 0, sizeof(ifr));
73  strncpy(ifr.ifr_name, name_.c_str(), IF_NAMESIZE-1);
74  if (ioctl(tap_fd_, SIOCGIFHWADDR, (void *)&ifr) < 0) {
75  LOG(ERROR, "Packet Tap Error <" << errno << ": " << strerror(errno) <<
76  "> retrieving MAC address of the tap interface. BackTrace: "
77  << AgentBackTrace(1));
78  _Exit(0);
79  }
80  memcpy(mac_address_, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
81 
82  int raw;
83  if ((raw = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
84  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
85  strerror(errno) << "> creating socket"
86  << ". BackTrace: " << AgentBackTrace(1));
87  _Exit(0);
88  }
89 
90  memset(&ifr, 0, sizeof(ifr));
91  strncpy(ifr.ifr_name, name_.c_str(), IF_NAMESIZE-1);
92  if (ioctl(raw, SIOCGIFINDEX, (void *)&ifr) < 0) {
93  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
94  strerror(errno) << "> getting ifindex of the tap interface"
95  << ". BackTrace: " << AgentBackTrace(1));
96  _Exit(0);
97  }
98 
99  struct sockaddr_ll sll;
100  memset(&sll, 0, sizeof(struct sockaddr_ll));
101  sll.sll_family = AF_PACKET;
102  sll.sll_ifindex = ifr.ifr_ifindex;
103  sll.sll_protocol = htons(ETH_P_ALL);
104  if (bind(raw, (struct sockaddr *)&sll,
105  sizeof(struct sockaddr_ll)) < 0) {
106  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
107  strerror(errno) << "> binding the socket to the tap interface"
108  << ". BackTrace: " << AgentBackTrace(1));
109  _Exit(0);
110  }
111 
112  // Set tx-buffer count
113  memset(&ifr, 0, sizeof(ifr));
114  strncpy(ifr.ifr_name, name_.c_str(), IF_NAMESIZE-1);
115  if (ioctl(raw, SIOCGIFTXQLEN, (void *)&ifr) < 0) {
116  LOG(ERROR, "Packet Tap Error <" << errno << ": " << strerror(errno) <<
117  "> getting tx-buffer size. BackTrace: " << AgentBackTrace(1));
118  _Exit(0);
119  }
120 
121  uint32_t qlen = pkt_handler()->agent()->params()->pkt0_tx_buffer_count();
122  if (ifr.ifr_qlen < (int)qlen) {
123  ifr.ifr_qlen = qlen;
124  if (ioctl(raw, SIOCSIFTXQLEN, (void *)&ifr) < 0) {
125  LOG(ERROR, "Packet Tap Error <" << errno << ": "
126  << strerror(errno) << "> setting tx-buffer size"
127  << ". BackTrace: " << AgentBackTrace(1));
128  _Exit(0);
129  }
130  }
131 
132  memset(&ifr, 0, sizeof(ifr));
133  strncpy(ifr.ifr_name, name_.c_str(), IF_NAMESIZE-1);
134  if (ioctl(raw, SIOCGIFFLAGS, (void *)&ifr) < 0) {
135  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
136  strerror(errno) << "> getting socket flags"
137  << ". BackTrace: " << AgentBackTrace(1));
138  _Exit(0);
139  }
140 
141  ifr.ifr_flags |= IFF_UP;
142  if (ioctl(raw, SIOCSIFFLAGS, (void *)&ifr) < 0) {
143  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
144  strerror(errno) << "> setting socket flags"
145  << ". BackTrace: " << AgentBackTrace(1));
146  _Exit(0);
147  }
148  close(raw);
149 
150  boost::system::error_code ec;
151  input_.assign(tap_fd_, ec);
152  assert(!ec);
153 
155  AsyncRead();
156 }
157 
158 void Pkt0Interface::SendImpl(uint8_t *buff, uint16_t buff_len, const PacketBufferPtr &pkt,
159  buffer_list& buff_list) {
160  input_.async_write_some(buff_list,
161  boost::bind(&Pkt0Interface::WriteHandler, this,
162  boost::asio::placeholders::error,
163  boost::asio::placeholders::bytes_transferred, buff));
164 }
165 
168 
169  int raw_;
170  struct ifreq ifr;
171  memset(&ifr, 0, sizeof(ifr));
172  if ((raw_ = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
173  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
174  strerror(errno) << "> creating socket"
175  << ". BackTrace: " << AgentBackTrace(1));
176  _Exit(0);
177  }
178 
179  memset(&ifr, 0, sizeof(ifr));
180  strncpy(ifr.ifr_name,
181  pkt_handler()->agent()->pkt_interface_name().c_str(), IF_NAMESIZE-1);
182  if (ioctl(raw_, SIOCGIFINDEX, (void *)&ifr) < 0) {
183  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
184  strerror(errno) << "> getting ifindex of the " <<
185  "expception packet interface"
186  << ". BackTrace: " << AgentBackTrace(1));
187  _Exit(0);
188  }
189 
190  struct sockaddr_ll sll;
191  memset(&sll, 0, sizeof(struct sockaddr_ll));
192  sll.sll_family = AF_PACKET;
193  sll.sll_ifindex = ifr.ifr_ifindex;
194  sll.sll_protocol = htons(ETH_P_ALL);
195  if (bind(raw_, (struct sockaddr *)&sll,
196  sizeof(struct sockaddr_ll)) < 0) {
197  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
198  strerror(errno) << "> binding the socket to the tap interface"
199  << ". BackTrace: " << AgentBackTrace(1));
200  _Exit(0);
201  }
202 
203  memset(&ifr, 0, sizeof(ifr));
204  strncpy(ifr.ifr_name, name_.c_str(), IF_NAMESIZE-1);
205  if (ioctl(raw_, SIOCGIFFLAGS, (void *)&ifr) < 0) {
206  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
207  strerror(errno) << "> getting socket flags"
208  << ". BackTrace: " << AgentBackTrace(1));
209  _Exit(0);
210  }
211 
212  ifr.ifr_flags |= IFF_UP;
213  if (ioctl(raw_, SIOCSIFFLAGS, (void *)&ifr) < 0) {
214  LOG(ERROR, "Packet Tap Error <" << errno << ": " <<
215  strerror(errno) << "> setting socket flags"
216  << ". BackTrace: " << AgentBackTrace(1));
217  _Exit(0);
218  }
219  tap_fd_ = raw_;
220 
221  boost::system::error_code ec;
222  input_.assign(tap_fd_, ec);
223  assert(!ec);
224 
226  AsyncRead();
227 }
boost::shared_ptr< PacketBuffer > PacketBufferPtr
Definition: packet_buffer.h:18
void WriteHandler(const boost::system::error_code &error, std::size_t length, uint8_t *buff)
unsigned char mac_address_[ETHER_ADDR_LEN]
uint32_t pkt0_tx_buffer_count() const
Definition: agent_param.h:506
#define TUN_INTF_CLONE_DEV
PktHandler * pkt_handler() const
Agent * agent() const
Definition: pkt_handler.h:317
virtual void InitControlInterface()
std::string name_
AgentParam * params() const
Definition: agent.h:1218
std::string AgentBackTrace(int skip=1)
Definition: agent.cc:1187
boost::asio::posix::stream_descriptor input_
void SendImpl(uint8_t *buff, uint16_t buff_len, const PacketBufferPtr &pkt, buffer_list &buff_list)
#define LOG(_Level, _Msg)
Definition: logging.h:33
void set_pkt_interface_name(const std::string &name)
Definition: agent.h:947
virtual void InitControlInterface()