Skip to content

Instantly share code, notes, and snippets.

@bluecmd
Created February 11, 2019 17:59
Show Gist options
  • Select an option

  • Save bluecmd/65da56bfa5dc78a2a8964a5539fd58e7 to your computer and use it in GitHub Desktop.

Select an option

Save bluecmd/65da56bfa5dc78a2a8964a5539fd58e7 to your computer and use it in GitHub Desktop.
diff --git a/msgenu.h b/msgenu.h
index f61fe77a..aa18cbf0 100644
--- a/msgenu.h
+++ b/msgenu.h
@@ -2186,7 +2186,8 @@ LOGM_DLL_IMPORT int panel_command_capture( char* cmd, char** resp );
#define HHC03808 "%1d:%04X %s: %s: Cannot unregister guest IP address %s"
#define HHC03809 "%1d:%04X %s: %s: Requested MTU %s too large; decreasing to %s bytes"
#define HHC03810 "%1d:%04X %s: %s: Input dropped: %s"
-//efine HHC03811 - HHC03849 (available)
+#define HHC03811 "%1d:%04X %s: %s: Output dropped: %s"
+//efine HHC03812 - HHC03849 (available)
//efine HHC03850 - HHC03899 (available)
diff --git a/qeth.c b/qeth.c
index aab6fe80..67ab19bd 100644
--- a/qeth.c
+++ b/qeth.c
@@ -3337,44 +3337,58 @@ static QRC write_buffered_packets( DEVBLK* dev, OSA_GRP *grp,
pkt = dev->buf;
pktlen = dev->buflen;
- /* I know the following looks pretty weird but it seems to be */
- /* necessary when using IPv6 over layer 3. IPv6 uses ICMPv6 Neighbor */
- /* Solicitation (NS) & Neighbor Advertisment (NA) to determine the */
- /* link layer address (i.e. Ethernet MAC) for an IPv6 address. When */
- /* the guest sends out a NS, this function sends the packet over the */
- /* tun to the host, whereupon the host duly ignores the packet. Hence */
- /* this function, and function process_l3_icmpv6_packet, responds to */
- /* the NS with a NA. It seems that the NA must contain a link local */
- /* address, otherwise the guest ignores the packet. However, after */
- /* the guest has received an NA with a link local address every IPv6 */
- /* packet from the guest is an Ethernet frame containing the IPv6 */
- /* packet. Perhaps that's how OSD's actually work? IPv6 packets to */
- /* the guest don't need to be Ethernet frames. */
- /* */
- /* Originally the whole of this section of code was surrounded by an */
- /* '#if defined(ENABLE_IPV6)' and '#endif'. However, implementing */
- /* zLinuz layer 3 support showed that zLinux emmitted IPv4 ARP */
- /* frames, which if sent to the tun interface, upset the tun, hence */
- /* the dropthishing checking. */
- /* */
- dropthisthing = FALSE;
- if (grp->l3)
- {
- eth = (ETHFRM*)pkt;
- if (memcmp( &eth->bSrcMAC[0], &grp->iMAC, IFHWADDRLEN ) == 0)
- {
- FETCH_HW( hwEthernetType, eth->hwEthernetType );
- if (hwEthernetType == ETH_TYPE_IP || hwEthernetType == ETH_TYPE_IPV6)
- {
- pkt += sizeof(ETHFRM);
- pktlen -= sizeof(ETHFRM);
- } else {
- dropthisthing = TRUE;
- }
- }
- }
-
- if (dropthisthing == TRUE) continue;
+ /* PROGRAMMING NOTE */
+ /* */
+ /* I know the following looks pretty weird but it seems to be */
+ /* necessary when using IPv6 over layer 3. IPv6 uses ICMPv6 Neighbor */
+ /* Solicitation (NS) & Neighbor Advertisment (NA) to determine the */
+ /* link layer address (i.e. Ethernet MAC) for an IPv6 address. When */
+ /* the guest sends out a NS, this function sends the packet over the */
+ /* tun to the host, whereupon the host duly ignores the packet. Hence */
+ /* this function, and function process_l3_icmpv6_packet, responds to */
+ /* the NS with a NA. It seems that the NA must contain a link local */
+ /* address, otherwise the guest ignores the packet. However, after */
+ /* the guest has received an NA with a link local address every IPv6 */
+ /* packet from the guest is an Ethernet frame containing the IPv6 */
+ /* packet. Perhaps that's how OSD's actually work? IPv6 packets to */
+ /* the guest don't need to be Ethernet frames. */
+ /* */
+ /* Originally the whole of this section of code was surrounded by an */
+ /* '#if defined(ENABLE_IPV6)' and '#endif'. However, implementing */
+ /* zLinuz layer 3 support showed that zLinux emmitted IPv4 ARP */
+ /* frames, which if sent to the tun interface, upset the tun, hence */
+ /* the following special handling. */
+ /* */
+ if (grp->l3)
+ {
+ /* Might this be a L2 IPv6 Ethernet Frame? (and not an L3 IP packet?)
+ (Refer to PROGRAMMING NOTE just above regarding IPv6 over layer 3)
+ */
+ if (HDR_ID_LAYER2 == hdr_id)
+ {
+ eth = (ETHFRM*) pkt;
+ FETCH_HW( hwEthernetType, eth->hwEthernetType );
+ if (1
+ && ETH_TYPE_IP != hwEthernetType
+ && ETH_TYPE_IPV6 != hwEthernetType
+ )
+ {
+ /* Can't write L2 Ethernet frame to L3 tun device! */
+ dev->qdio.dropcnt++;
+ if (grp->debugmask & DBGQETHDROP)
+ {
+ // "%1d:%04X %s: %s: Output dropped: %s"
+ WRMSG( HHC03811, "W", LCSS_DEVNUM,
+ dev->typname, grp->ttifname, "L2 frame on tun device" );
+ }
+ continue; /* (don't write this packet) */
+ }
+
+ /* Bump past L2 Ethernet header to actual L3 IP packet */
+ pkt += sizeof( ETHFRM );
+ pktlen -= sizeof( ETHFRM );
+ }
+ }
/* Debugging */
if (grp->debugmask & DBGQETHPACKET)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment