Updated: Enabling tap interfaces in pfinet

Ralph Ronnquist <[email protected]> Wed, 29 Jul 2026 01:07:31 +1000
Newsgroups gmane.os.hurd.bugs
Message-ID <amjFsxFZOf9k-P4W@smulan>
--5nFSbc5YYuwIWgtT
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

This is a follow-on patch for the tap implementation, with a bit of
cleanup after feedback from Alperen Erkan <[email protected]>

Ralph.

--5nFSbc5YYuwIWgtT
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="0002-Code-cleanup-for-Ethernet-level-2-implementation.patch"

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


--5nFSbc5YYuwIWgtT--