@@ -62,11 +62,11 @@ static void virtio_net_update_status(virtio_net_state_t *vnet, uint32_t status)
6262 return ;
6363
6464 /* Reset */
65- int tap_fd = vnet -> tap_fd ;
65+ netdev_t peer = vnet -> peer ;
6666 uint32_t * ram = vnet -> ram ;
6767 void * priv = vnet -> priv ;
6868 memset (vnet , 0 , sizeof (* vnet ));
69- vnet -> tap_fd = tap_fd , vnet -> ram = ram ;
69+ vnet -> peer = peer , vnet -> ram = ram ;
7070 vnet -> priv = priv ;
7171}
7272
@@ -113,6 +113,64 @@ static bool vnet_iovec_read(struct iovec **vecs,
113113 return n && !* nvecs ;
114114}
115115
116+ static ssize_t handle_read (netdev_t * netdev ,
117+ virtio_net_queue_t * queue ,
118+ struct iovec * iovs_cursor ,
119+ size_t niovs )
120+ {
121+ ssize_t plen = 0 ;
122+ switch (netdev -> type ) {
123+ case NET_CLIENT_DRIVER_TAP :
124+ plen = readv (netdev -> op .tap .tap_fd , iovs_cursor , niovs );
125+ if (plen < 0 && (errno == EWOULDBLOCK || errno == EAGAIN )) {
126+ queue -> fd_ready = false;
127+ return -1 ;
128+ }
129+ if (plen < 0 ) {
130+ plen = 0 ;
131+ fprintf (stderr , "[VNET] could not read packet: %s\n" ,
132+ strerror (errno ));
133+ }
134+ break ;
135+ case NET_CLIENT_DRIVER_USER :
136+ /* TODO: handle read */
137+ break ;
138+ default :
139+ break ;
140+ }
141+
142+ return plen ;
143+ }
144+
145+ static ssize_t handle_write (netdev_t * netdev ,
146+ virtio_net_queue_t * queue ,
147+ struct iovec * iovs_cursor ,
148+ size_t niovs )
149+ {
150+ ssize_t plen = 0 ;
151+ switch (netdev -> type ) {
152+ case NET_CLIENT_DRIVER_TAP :
153+ plen = writev (netdev -> op .tap .tap_fd , iovs_cursor , niovs );
154+ if (plen < 0 && (errno == EWOULDBLOCK || errno == EAGAIN )) {
155+ queue -> fd_ready = false;
156+ return -1 ;
157+ }
158+ if (plen < 0 ) {
159+ plen = 0 ;
160+ fprintf (stderr , "[VNET] could not write packet: %s\n" ,
161+ strerror (errno ));
162+ }
163+ break ;
164+ case NET_CLIENT_DRIVER_USER :
165+ /* TODO: handle slirp_input */
166+ break ;
167+ default :
168+ break ;
169+ }
170+
171+ return plen ;
172+ }
173+
116174/* Require existing 'desc_idx' to use as iteration variable, and input
117175 * 'buffer_idx'.
118176 */
@@ -186,18 +244,10 @@ static bool vnet_iovec_read(struct iovec **vecs,
186244 virtio_header , sizeof (virtio_header )); \
187245 } \
188246 \
189- ssize_t plen = \
190- VERB ##v (vnet->tap_fd, buffer_iovs_cursor, buffer_niovs); \
191- if (plen < 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { \
192- queue->fd_ready = false; \
247+ ssize_t plen = handle_ ##VERB (&vnet->peer, queue, \
248+ buffer_iovs_cursor, buffer_niovs); \
249+ if (plen < 0) \
193250 break; \
194- } \
195- if (plen < 0) { \
196- plen = 0; \
197- fprintf(stderr, "[VNET] could not " #VERB " packet: %s\n", \
198- strerror(errno)); \
199- } \
200- \
201251 /* consume from available queue, write to used queue */ \
202252 queue -> last_avail ++ ; \
203253 ram [queue -> QueueUsed + 1 + (new_used % queue -> QueueNum ) * 2 ] = \
@@ -223,15 +273,25 @@ void virtio_net_refresh_queue(virtio_net_state_t *vnet)
223273 (vnet -> Status & VIRTIO_STATUS__DEVICE_NEEDS_RESET ))
224274 return ;
225275
226- struct pollfd pfd = {vnet -> tap_fd , POLLIN | POLLOUT , 0 };
227- poll (& pfd , 1 , 0 );
228- if (pfd .revents & POLLIN ) {
229- vnet -> queues [VNET_QUEUE_RX ].fd_ready = true;
230- virtio_net_try_rx (vnet );
231- }
232- if (pfd .revents & POLLOUT ) {
233- vnet -> queues [VNET_QUEUE_TX ].fd_ready = true;
234- virtio_net_try_tx (vnet );
276+ net_client_driver_t client_type = vnet -> peer .type ;
277+ switch (client_type ) {
278+ case NET_CLIENT_DRIVER_TAP :
279+ struct pollfd pfd = {vnet -> peer .op .tap .tap_fd , POLLIN | POLLOUT , 0 };
280+ poll (& pfd , 1 , 0 );
281+ if (pfd .revents & POLLIN ) {
282+ vnet -> queues [VNET_QUEUE_RX ].fd_ready = true;
283+ virtio_net_try_rx (vnet );
284+ }
285+ if (pfd .revents & POLLOUT ) {
286+ vnet -> queues [VNET_QUEUE_TX ].fd_ready = true;
287+ virtio_net_try_tx (vnet );
288+ }
289+ break ;
290+ case NET_CLIENT_DRIVER_USER :
291+ /* TODO: handle slirp input/output */
292+ break ;
293+ default :
294+ break ;
235295 }
236296}
237297
@@ -433,7 +493,7 @@ void virtio_net_write(hart_t *vm,
433493 }
434494}
435495
436- bool virtio_net_init (virtio_net_state_t * vnet )
496+ bool virtio_net_init (virtio_net_state_t * vnet , const char * client )
437497{
438498 if (vnet_dev_cnt >= VNET_DEV_CNT_MAX ) {
439499 fprintf (stderr ,
@@ -444,23 +504,10 @@ bool virtio_net_init(virtio_net_state_t *vnet)
444504 /* Allocate memory for the private member */
445505 vnet -> priv = & vnet_configs [vnet_dev_cnt ++ ];
446506
447- vnet -> tap_fd = open ("/dev/net/tun" , O_RDWR );
448- if (vnet -> tap_fd < 0 ) {
449- fprintf (stderr , "failed to open TAP device: %s\n" , strerror (errno ));
507+ if (!net_client_init (& vnet -> peer , client )) {
508+ fprintf (stderr , "Fail to init client device %s\n" , client );
450509 return false;
451510 }
452511
453- /* Specify persistent tap device */
454- struct ifreq ifreq = {.ifr_flags = IFF_TAP | IFF_NO_PI };
455- strncpy (ifreq .ifr_name , TAP_INTERFACE , sizeof (ifreq .ifr_name ));
456- if (ioctl (vnet -> tap_fd , TUNSETIFF , & ifreq ) < 0 ) {
457- fprintf (stderr , "failed to allocate TAP device: %s\n" , strerror (errno ));
458- return false;
459- }
460-
461- fprintf (stderr , "allocated TAP interface: %s\n" , ifreq .ifr_name );
462- assert (fcntl (vnet -> tap_fd , F_SETFL ,
463- fcntl (vnet -> tap_fd , F_GETFL , 0 ) | O_NONBLOCK ) >= 0 );
464-
465512 return true;
466513}
0 commit comments