iPXE
tap.c File Reference

The TAP driver. More...

#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <ipxe/linux_api.h>
#include <ipxe/list.h>
#include <ipxe/linux.h>
#include <ipxe/malloc.h>
#include <ipxe/device.h>
#include <ipxe/netdevice.h>
#include <ipxe/iobuf.h>
#include <ipxe/ethernet.h>
#include <ipxe/settings.h>
#include <ipxe/socket.h>
#include <linux/socket.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_tun.h>

Go to the source code of this file.

Data Structures

struct  tap_nic

Macros

#define _SYS_SOCKET_H
#define __GLIBC__   2
#define RX_BUF_SIZE   1536
#define RX_QUOTA   4

Functions

static int tap_open (struct net_device *netdev)
 Open the TAP device.
static void tap_close (struct net_device *netdev)
 Close the TAP device.
static int tap_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit an ethernet packet.
static void tap_poll (struct net_device *netdev)
 Poll for new packets.
static void tap_irq (struct net_device *netdev, int enable)
 Set irq.
static int tap_probe (struct linux_device *device, struct linux_device_request *request)
 Handle a device request for the tap driver.
static void tap_remove (struct linux_device *device)
 Remove the device.
 LINUX_ROM ("tap", "Linux TUN/TAP NIC")

Variables

static const uint8_t tap_default_mac [ETH_ALEN]
 Default MAC address.
static struct net_device_operations tap_operations
 Tap operations.
struct linux_driver tap_driver __linux_driver
 Tap linux_driver.

Detailed Description

The TAP driver.

The TAP is a Virtual Ethernet network device.

Definition in file tap.c.

Macro Definition Documentation

◆ _SYS_SOCKET_H

#define _SYS_SOCKET_H

Definition at line 34 of file tap.c.

◆ __GLIBC__

#define __GLIBC__   2

Definition at line 35 of file tap.c.

◆ RX_BUF_SIZE

#define RX_BUF_SIZE   1536

Definition at line 42 of file tap.c.

◆ RX_QUOTA

#define RX_QUOTA   4

Definition at line 43 of file tap.c.

Referenced by tap_poll().

Function Documentation

◆ tap_open()

int tap_open ( struct net_device * netdev)
static

Open the TAP device.

Definition at line 64 of file tap.c.

65{
66 struct tap_nic * nic = netdev->priv;
67 struct ifreq ifr;
68 int ret;
69
70 nic->fd = linux_open("/dev/net/tun", O_RDWR);
71 if (nic->fd < 0) {
72 DBGC(nic, "tap %p open('/dev/net/tun') = %d (%s)\n", nic, nic->fd, linux_strerror(linux_errno));
73 return nic->fd;
74 }
75
76 memset(&ifr, 0, sizeof(ifr));
77 /* IFF_NO_PI for no extra packet information */
78 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
79 strncpy(ifr.ifr_name, nic->interface, IFNAMSIZ);
80 DBGC(nic, "tap %p interface = '%s'\n", nic, nic->interface);
81
82 ret = linux_ioctl(nic->fd, TUNSETIFF, &ifr);
83
84 if (ret != 0) {
85 DBGC(nic, "tap %p ioctl(%d, ...) = %d (%s)\n", nic, nic->fd, ret, linux_strerror(linux_errno));
86 linux_close(nic->fd);
87 return ret;
88 }
89
90 /* Set nonblocking mode to make tap_poll easier */
91 ret = linux_fcntl(nic->fd, F_SETFL, O_NONBLOCK);
92
93 if (ret != 0) {
94 DBGC(nic, "tap %p fcntl(%d, ...) = %d (%s)\n", nic, nic->fd, ret, linux_strerror(linux_errno));
95 linux_close(nic->fd);
96 return ret;
97 }
98
99 return 0;
100}
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC(...)
Definition compiler.h:505
void * memset(void *dest, int character, size_t len) __nonnull
int __asmcall linux_open(const char *pathname, int flags,...)
int linux_errno
int __asmcall linux_ioctl(int fd, unsigned long request,...)
int __asmcall linux_close(int fd)
int __asmcall linux_fcntl(int fd, int cmd,...)
const char *__asmcall linux_strerror(int linux_errno)
char * strncpy(char *dest, const char *src, size_t max)
Copy string.
Definition string.c:361
Definition nic.h:49
Definition tap.c:52

References DBGC, linux_close(), linux_errno, linux_fcntl(), linux_ioctl(), linux_open(), linux_strerror(), memset(), netdev, and strncpy().

◆ tap_close()

void tap_close ( struct net_device * netdev)
static

Close the TAP device.

Definition at line 103 of file tap.c.

104{
105 struct tap_nic * nic = netdev->priv;
106 linux_close(nic->fd);
107}

References linux_close(), and netdev.

◆ tap_transmit()

int tap_transmit ( struct net_device * netdev,
struct io_buffer * iobuf )
static

Transmit an ethernet packet.

The packet can be written to the TAP device and marked as complete immediately.

Definition at line 114 of file tap.c.

115{
116 struct tap_nic * nic = netdev->priv;
117 int rc;
118
119 /* Pad and align packet */
120 iob_pad(iobuf, ETH_ZLEN);
121
122 rc = linux_write(nic->fd, iobuf->data, iobuf->tail - iobuf->data);
123 DBGC2(nic, "tap %p wrote %d bytes\n", nic, rc);
125
126 return 0;
127}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define DBGC2(...)
Definition compiler.h:522
#define ETH_ZLEN
Definition if_ether.h:11
void iob_pad(struct io_buffer *iobuf, size_t min_len)
Pad I/O buffer.
Definition iobpad.c:50
ssize_t __asmcall linux_write(int fd, const void *buf, size_t count)
static void netdev_tx_complete(struct net_device *netdev, struct io_buffer *iobuf)
Complete network transmission.
Definition netdevice.h:767
void * data
Start of data.
Definition iobuf.h:53
void * tail
End of data.
Definition iobuf.h:55

References io_buffer::data, DBGC2, ETH_ZLEN, iob_pad(), linux_write(), netdev, netdev_tx_complete(), rc, and io_buffer::tail.

◆ tap_poll()

void tap_poll ( struct net_device * netdev)
static

Poll for new packets.

Definition at line 130 of file tap.c.

131{
132 struct tap_nic * nic = netdev->priv;
133 struct pollfd pfd;
134 struct io_buffer * iobuf;
135 unsigned int quota = RX_QUOTA;
136 int r;
137
138 pfd.fd = nic->fd;
139 pfd.events = POLLIN;
140 if (linux_poll(&pfd, 1, 0) == -1) {
141 DBGC(nic, "tap %p poll failed (%s)\n", nic, linux_strerror(linux_errno));
142 return;
143 }
144 if ((pfd.revents & POLLIN) == 0)
145 return;
146
147 /* At this point we know there is at least one new packet to be read */
148
149 iobuf = alloc_iob(RX_BUF_SIZE);
150 if (! iobuf)
151 goto allocfail;
152
153 while (quota-- &&
154 ((r = linux_read(nic->fd, iobuf->data, RX_BUF_SIZE)) > 0)) {
155 DBGC2(nic, "tap %p read %d bytes\n", nic, r);
156
157 iob_put(iobuf, r);
158 netdev_rx(netdev, iobuf);
159
160 iobuf = alloc_iob(RX_BUF_SIZE);
161 if (! iobuf)
162 goto allocfail;
163 }
164
165 free_iob(iobuf);
166 return;
167
168allocfail:
169 DBGC(nic, "tap %p alloc_iob failed\n", nic);
170}
#define RX_BUF_SIZE
Definition 3c90x.h:269
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
#define iob_put(iobuf, len)
Definition iobuf.h:125
ssize_t __asmcall linux_read(int fd, void *buf, size_t count)
int __asmcall linux_poll(struct pollfd *fds, unsigned int nfds, int timeout)
static const uint8_t r[3][4]
MD4 shift amounts.
Definition md4.c:54
void netdev_rx(struct net_device *netdev, struct io_buffer *iobuf)
Add packet to receive queue.
Definition netdevice.c:549
A persistent I/O buffer.
Definition iobuf.h:38
#define RX_QUOTA
Definition tap.c:43

References alloc_iob(), io_buffer::data, DBGC, DBGC2, free_iob(), iob_put, linux_errno, linux_poll(), linux_read(), linux_strerror(), netdev, netdev_rx(), r, RX_BUF_SIZE, and RX_QUOTA.

◆ tap_irq()

void tap_irq ( struct net_device * netdev,
int enable )
static

Set irq.

Not used on linux, provide a dummy implementation.

Definition at line 177 of file tap.c.

178{
179 struct tap_nic *nic = netdev->priv;
180
181 DBGC(nic, "tap %p irq enable = %d\n", nic, enable);
182}

References DBGC, and netdev.

◆ tap_probe()

int tap_probe ( struct linux_device * device,
struct linux_device_request * request )
static

Handle a device request for the tap driver.

Definition at line 194 of file tap.c.

195{
196 struct linux_setting *if_setting;
197 struct net_device *netdev;
198 struct tap_nic *nic;
199 int rc;
200
201 netdev = alloc_etherdev(sizeof(*nic));
202 if (! netdev)
203 return -ENOMEM;
204
206 nic = netdev->priv;
208 netdev->dev = &device->dev;
209 memcpy ( netdev->hw_addr, tap_default_mac, ETH_ALEN );
210 memset(nic, 0, sizeof(*nic));
211
212 /* Look for the mandatory if setting */
213 if_setting = linux_find_setting("if", &request->settings);
214
215 /* No if setting */
216 if (! if_setting) {
217 printf("tap missing a mandatory if setting\n");
218 rc = -EINVAL;
219 goto err_settings;
220 }
221
222 nic->interface = if_setting->value;
223 snprintf ( device->dev.name, sizeof ( device->dev.name ), "%s",
224 nic->interface );
226 if_setting->applied = 1;
227
228 /* Apply rest of the settings */
229 linux_apply_settings(&request->settings, &netdev->settings.settings);
230
231 /* Register network device */
232 if ((rc = register_netdev(netdev)) != 0)
233 goto err_register;
234
236
237 return 0;
238
240err_register:
241err_settings:
244 return rc;
245}
#define BUS_TYPE_TAP
TAP bus type.
Definition device.h:59
struct net_device * alloc_etherdev(size_t priv_size)
Allocate Ethernet device.
Definition ethernet.c:265
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOMEM
Not enough space.
Definition errno.h:535
u8 request[0]
List of IEs requested.
Definition ieee80211.h:2
#define ETH_ALEN
Definition if_ether.h:9
static void linux_set_drvdata(struct linux_device *device, void *priv)
Set linux device driver-private data.
Definition linux.h:78
void linux_apply_settings(struct list_head *new_settings, struct settings *settings_block)
Apply a list of linux settings to a settings block.
struct linux_setting * linux_find_setting(char *name, struct list_head *settings)
Look for the last occurrence of a setting with the specified name.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void unregister_netdev(struct net_device *netdev)
Unregister network device.
Definition netdevice.c:942
int register_netdev(struct net_device *netdev)
Register network device.
Definition netdevice.c:760
static void netdev_link_up(struct net_device *netdev)
Mark network device as having link up.
Definition netdevice.h:789
static void netdev_init(struct net_device *netdev, struct net_device_operations *op)
Initialise a network device.
Definition netdevice.h:519
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition netdevice.h:532
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:576
unsigned int bus_type
Bus type.
Definition device.h:25
A hardware device.
Definition device.h:77
struct device_description desc
Device description.
Definition device.h:83
char name[40]
Name.
Definition device.h:79
A device request setting.
Definition linux.h:109
int applied
Was the setting already applied?
Definition linux.h:115
char * value
Value.
Definition linux.h:113
A network device.
Definition netdevice.h:353
static struct net_device_operations tap_operations
Tap operations.
Definition tap.c:185
static const uint8_t tap_default_mac[ETH_ALEN]
Default MAC address.
Definition tap.c:60
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition vsprintf.c:465
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383

References alloc_etherdev(), linux_setting::applied, device_description::bus_type, BUS_TYPE_TAP, device::desc, EINVAL, ENOMEM, ETH_ALEN, linux_apply_settings(), linux_find_setting(), linux_set_drvdata(), memcpy(), memset(), device::name, netdev, netdev_init(), netdev_link_up(), netdev_nullify(), netdev_put(), printf(), rc, register_netdev(), request, snprintf(), tap_default_mac, tap_operations, unregister_netdev(), and linux_setting::value.

◆ tap_remove()

void tap_remove ( struct linux_device * device)
static

Remove the device.

Definition at line 248 of file tap.c.

249{
254}
static void * linux_get_drvdata(struct linux_device *device)
Get linux device driver-private data.
Definition linux.h:89

References linux_get_drvdata(), netdev, netdev_nullify(), netdev_put(), and unregister_netdev().

◆ LINUX_ROM()

LINUX_ROM ( "tap" ,
"Linux TUN/TAP NIC"  )

Variable Documentation

◆ tap_default_mac

const uint8_t tap_default_mac[ETH_ALEN]
static
Initial value:
=
{ 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 }

Default MAC address.

Definition at line 60 of file tap.c.

61 { 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 };

Referenced by tap_probe().

◆ tap_operations

struct net_device_operations tap_operations
static
Initial value:
= {
.open = tap_open,
.close = tap_close,
.transmit = tap_transmit,
.poll = tap_poll,
.irq = tap_irq,
}
static void tap_poll(struct net_device *netdev)
Poll for new packets.
Definition tap.c:130
static int tap_open(struct net_device *netdev)
Open the TAP device.
Definition tap.c:64
static void tap_close(struct net_device *netdev)
Close the TAP device.
Definition tap.c:103
static int tap_transmit(struct net_device *netdev, struct io_buffer *iobuf)
Transmit an ethernet packet.
Definition tap.c:114
static void tap_irq(struct net_device *netdev, int enable)
Set irq.
Definition tap.c:177

Tap operations.

Definition at line 185 of file tap.c.

185 {
186 .open = tap_open,
187 .close = tap_close,
188 .transmit = tap_transmit,
189 .poll = tap_poll,
190 .irq = tap_irq,
191};

Referenced by tap_probe().

◆ __linux_driver

struct linux_driver tap_driver __linux_driver
Initial value:
= {
.name = "tap",
.probe = tap_probe,
.remove = tap_remove,
}
static void tap_remove(struct linux_device *device)
Remove the device.
Definition tap.c:248
static int tap_probe(struct linux_device *device, struct linux_device_request *request)
Handle a device request for the tap driver.
Definition tap.c:194

Tap linux_driver.

Definition at line 257 of file tap.c.

257 {
258 .name = "tap",
259 .probe = tap_probe,
260 .remove = tap_remove,
261};