Re: Updated: Enabling tap interfaces in pfinet

Samuel Thibault <[email protected]> Wed, 29 Jul 2026 17:53:33 +0200
Newsgroups gmane.os.hurd.bugs
Organization I am not organized
Message-ID <amoh_YGeJ_Y6JFZC@end>
Hello,

Ralph Ronnquist, le mer. 29 juil. 2026 01:07:31 +1000, a ecrit:
> This is a follow-on patch for the tap implementation, with a bit of
> cleanup after feedback from Alperen Erkan <[email protected]>

Please merge the two, so I just review the merged version instead of two
separate patches.

Samuel

> From 2c68b2e7ea443c167f3d9280132fa53b40fe7d83 Mon Sep 17 00:00:00 2001
> From: Ralph Ronnquist <[email protected]>
> Date: Tue, 28 Jul 2026 17:50:09 +1000
> Subject: [PATCH 2/2] Code cleanup for Ethernet level 2 implementation
> 
> ---
>  pfinet/linux-src/include/linux/if_ether.h | 44 +++++++++++++++
>  pfinet/linux-src/net/core/dev.c           |  3 +-
>  pfinet/tunnel.c                           | 65 +++--------------------
>  3 files changed, 54 insertions(+), 58 deletions(-)
> 
> diff --git a/pfinet/linux-src/include/linux/if_ether.h b/pfinet/linux-src/include/linux/if_ether.h
> index 99bb97fa..efb566e0 100644
> --- a/pfinet/linux-src/include/linux/if_ether.h
> +++ b/pfinet/linux-src/include/linux/if_ether.h
> @@ -87,6 +87,50 @@ struct ethhdr
>  	unsigned short	h_proto;		/* packet type ID field	*/
>  };
>  
> +/* Alternative Ethernet header with VLAN tagging. The header without
> +   VLAN tagging (the original header) is found in <net/ethernet.h>.
> +   This header modelling accounts for packets optionally having VLAN
> +   tagging inserted before the ether_type field.
> +*/
> +
> +struct ethhdr_vlan
> +{
> +    uint8_t  h_dest[ETH_ALEN];        /* destination eth addr */
> +    uint8_t  h_source[ETH_ALEN];      /* source ether addr    */
> +    uint16_t h_vlan_tag;              /* htons( 0x8100 ) */
> +    uint16_t h_vlan_id;               /* VLAN ID */
> +    uint16_t h_proto;                 /* packet type ID field */
> +};
> +
> +/* Generic header that incorporates both without and with VLAN alternatives */
> +union ethhdr_either {
> +    struct ethhdr without_vlan;
> +    struct ethhdr_vlan with_vlan;
> +};
> +
> +/* Repeating from net/ethernet.h */
> +#define ETHERTYPE_VLAN 0x8100
> +
> +/* Detecting presence of VLAN tag */
> +static inline int has_vlan_tag(unsigned char *frame) {
> +    uint16_t v = ntohs( ((struct ethhdr_vlan*)frame)->h_vlan_tag );
> +    return ( v == ETHERTYPE_VLAN );
> +}
> +
> +/* Obtain ether_type handling optional VLAN tag. */
> +static inline uint16_t get_protocol(unsigned char *frame)
> +{
> +    return ntohs( has_vlan_tag(frame)?
> +		  (((struct ethhdr_vlan*)frame)->h_proto) :
> +		  (((struct ethhdr*)frame)->h_proto) );
> +}
> +
> +/* Obtain payload base address handling optional VLAN tag */
> +static inline unsigned char *get_ether_payload_p(unsigned char *frame) {
> +    return frame + ( has_vlan_tag(frame)?
> +		     sizeof(struct ethhdr_vlan) : sizeof(struct ethhdr) );
> +}
> +
>  /*
>   *	We Have changed the ethernet statistics collection data. This
>   *	is just for partial compatibility for now.
> diff --git a/pfinet/linux-src/net/core/dev.c b/pfinet/linux-src/net/core/dev.c
> index 2f480865..93e5aab1 100644
> --- a/pfinet/linux-src/net/core/dev.c
> +++ b/pfinet/linux-src/net/core/dev.c
> @@ -923,7 +923,8 @@ void net_bh(void)
>  		 */
>  
>  		/* XXX until we figure out every place to modify.. */
> -		if ( skb->nh.raw < skb->data || skb->nh.raw > skb->data + 20 ) 
> +		if ( skb->nh.raw < skb->data ||
> +		     skb->nh.raw > skb->data + sizeof(struct ethhdr_vlan)) 
>  		    skb->h.raw = skb->nh.raw = skb->data;
>  
>  		if (skb->mac.raw < skb->head || skb->mac.raw > skb->data) {
> diff --git a/pfinet/tunnel.c b/pfinet/tunnel.c
> index b22cd2a2..b7e4ab53 100644
> --- a/pfinet/tunnel.c
> +++ b/pfinet/tunnel.c
> @@ -58,8 +58,6 @@ struct tunnel_device
>    struct net_device_stats stats;
>  };
>  
> -static int istap = 0;
> -
>  /* Linked list of all tunnel devices.  */
>  struct tunnel_device *tunnel_dev;
>  
> @@ -186,8 +184,6 @@ setup_tunnel_device (char *name, struct device **device)
>    else
>      base_name = name;
>    
> -  istap = ( strncmp( base_name, "tap", 3 ) == 0 );
> -
>    dev->name = strdup (base_name);
>  
>    dev->get_stats = tunnel_get_stats;
> @@ -198,7 +194,7 @@ setup_tunnel_device (char *name, struct device **device)
>    dev->hard_start_xmit = tunnel_xmit;
>    dev->set_multicast_list = tunnel_set_multi;
>  
> -  if ( istap ) {
> +  if ( strncmp( base_name, "tap", 3 ) == 0 ) {
>        /* The setup for a tap is most similar the ethernet.c */
>        dev->hard_header = eth_header;
>        dev->rebuild_header = eth_rebuild_header;
> @@ -214,12 +210,8 @@ setup_tunnel_device (char *name, struct device **device)
>        dev->change_flags = tunnel_change_flags;
>  
>        // We *know* that ETH_ALEN == 6
> -      char *nametail = name + strlen(name) - 4;
> -      assert_backtrace ( nametail >= name );
> -      memcpy( dev->dev_addr, (char[ETH_ALEN]) {
> -	      0x06, 'H', 'u', 'r', 'd', 0xff & ( nametail[3] - '0' )
> -	  }, ETH_ALEN );
> -
> +      memcpy( dev->dev_addr, "\006Tap\000\000", 6 );
> +      sscanf( name, "tap%u", (unsigned int*)&dev->dev_addr[4] );
>    } else {
>        /* These are the ones set by drivers/net/ppp_generic.c::ppp_net_init.  */
>        dev->hard_header = 0;
> @@ -396,48 +388,6 @@ trivfs_S_io_read (struct trivfs_protid *cred,
>    return 0;
>  }
>  
> -/* Alternative Ethernet header with VLAN tagging. The header without
> -   VLAN tagging (the original header) is found in <net/ethernet.h>.
> -   This header modelling accounts for packets optionally having VLAN
> -   tagging inserted before the ether_type field.
> -*/
> -
> -struct ethhdr_vlan {
> -    uint8_t  h_dest[ETH_ALEN];        /* destination eth addr */
> -    uint8_t  h_source[ETH_ALEN];      /* source ether addr    */
> -    uint16_t h_vlan_tag;              /* htons( 0x8100 ) */
> -    uint16_t h_vlan_id;               /* VLAN ID */
> -    uint16_t h_proto;                 /* packet type ID field */
> -};
> -
> -union ethhdr_either {
> -    struct ethhdr without_vlan;
> -    struct ethhdr_vlan with_vlan;
> -};
> -
> -/* Repeating from net/ethernet.h */
> -#define ETHERTYPE_VLAN 0x8100
> -
> -/* Detecting presence of VLAN tag */
> -static inline int has_vlan_tag(unsigned char *frame) {
> -    uint16_t v = ntohs( ((struct ethhdr_vlan*)frame)->h_vlan_tag );
> -    return ( v == ETHERTYPE_VLAN );
> -}
> -
> -/* Obtain ether_type handling optional VLAN tag. */
> -static inline uint16_t get_protocol(unsigned char *frame)
> -{
> -    return ntohs( has_vlan_tag(frame)?
> -		  (((struct ethhdr_vlan*)frame)->h_proto) :
> -		  (((struct ethhdr*)frame)->h_proto) );
> -}
> -
> -/* Obtain payload base address handling optional VLAN tag */
> -static inline unsigned char *get_ether_payload_p(unsigned char *frame) {
> -    return frame + ( has_vlan_tag(frame)?
> -		     sizeof(struct ethhdr_vlan) : sizeof(struct ethhdr*) );
> -}
> -
>  /* Write data to an IO object.  If offset is -1, write at the object
>     maintained file pointer.  If the object is not seekable, offset is
>     ignored.  The amount successfully written is returned in amount.  A
> @@ -464,14 +414,15 @@ trivfs_S_io_write (struct trivfs_protid *cred,
>    if (! (cred->po->openmodes & O_WRITE))
>      return EBADF;
>  
> -  if ( istap && ( datalen < 18 ) ) // Too small Ethernet packet
> -    return EBADF;
> -
>    if (cred->pi.class != tunnel_class)
>      return EOPNOTSUPP;
>  
>    tdev = (struct tunnel_device *) cred->po->cntl->hook;
>  
> +  if ((tdev->dev.hard_header != 0) && (datalen < 18)) // small packet
> +    return EBADF;
> +
> +
>    pthread_mutex_lock (&tdev->lock);
>  
>    pthread_mutex_lock (&net_bh_lock);
> @@ -484,7 +435,7 @@ trivfs_S_io_write (struct trivfs_protid *cred,
>  
>    /* Drop it on the queue. */
>    skb->mac.raw = skb->data;
> -  if ( istap ) {
> +  if ( tdev->dev.hard_header != 0 ) {
>        skb->protocol = get_protocol(skb->data);
>        skb->h.raw = skb->nh.raw = get_ether_payload_p(skb->data);
>    } else {
> -- 
> 2.53.0
> 


-- 
Samuel
  bien sûr que ça convient mieux à tout le monde
  enfin, dans la mesure où tout le monde c'est comme moi
 -+- le consensus, c'est facile -+-