hercules-390 / hyperion

Hercules 390
Other
246 stars 69 forks source link

Setting of Source MAC address in outbound frame on LCS #208

Closed ivan-w closed 7 years ago

ivan-w commented 7 years ago

I am having an issue with an IP stack that doesn't set the Source MAC Address on outbound frames.

I am wondering if the LCS emulation shouldn't be setting the source MAC address of the LCS adapter when the source MAC address is all 0s in the outbound frame.

I guess it could be done somewhere in LCS_Write().

My rationale is as follows :

When I ping the IP layer in question, an ARP WHOAS is sent.. It is received and replied to (with an ARP response). But the IP layer seems to expect the LCS adapter to fill in the Source MAC Address - but it isn't, so the source address is 00:00:00:00:00:00 in the outbound ETH frame - which doesn't pass any bridge/vswitch/switch.

It MAY be a bug in the IP layer in question, but I am wondering if a 3172 running ICP wouldn't fill in the source MAC address if it wasn't set.

A lot of this is Fish's work - but since he no longer is in the list, I cannot assign him on this.

I'll see if I can forward this to him somehow.

--Ivan

jphartmann commented 7 years ago

Anyone including Fish can see and append to this issue by accessing it via https://github.com/hercules-390/hyperion/issues/208.

I wish you would too, Ivan. It creates a lot less noise for those who work on an issue. You will also be able to refer back to earlier appends easily so that your insight include stuff you saw two months earlier and, like the rest of us, promptly forgot.

Returning to the question at hand, a real adapter has a burned-in unique hardware address and the ability to use a locally administered address (02xxx or 04xxx depending on the notation). This would be a configuration option. Now, the the LCS virtual adapter cannot have a burned-in MAC, so it must clearly be configured with a locally administered MAC, and that has to come from the configuration file. Could it be that you somehow did not specify that. You did not show us the DEVICE statement.

ivan-w commented 7 years ago

On 3/22/2017 3:11 PM, John P. Hartmann wrote:

Returning to the question at hand, a real adapter has a burned-in unique hardware address and the ability to use a locally administered address (02xxx or 04xxx depending on the notation). This would be a configuration option. Now, the the LCS virtual adapter cannot have a burned-in MAC, so it must clearly be configured with a locally administered MAC, and that has to come from the configuration file. Could it be that you somehow did not specify that. You did not show us the DEVICE statement. The MAC address returned is the one given by the tap device opened + 1 (Shows in ctc_lcs.c :)

 /* Respond with a different MAC address for the LCS side */
 /* unless the TAP mechanism is designed as such          */
 /* cf : hostopts.h for an explanation                    */

if !defined(OPTION_TUNTAP_LCS_SAME_ADDR)

 reply.MAC_Address[5]++;

endif

(Around line 1638 in ctc_lcs.c)

The hercules configuration is as follows :

0E00.2 LCS -if tap0

tap0 is a persistent tap device attached to a bridge/vswitch :

brctl show

bridge name bridge id STP enabled interfaces br0 8000.000c29f8e34e yes eth0 tap0 tap1 tap2 tap3

brctl showmacs br0

port no mac addr is local? ageing timer 1 00:0c:29:f8:e3:4e yes 0.00 4 2e:92:a3:97:f7:3b yes 0.00 1 68:f7:28:37:15:00 no 10.02 2 82:42: cd :90:d3:0a yes 0.00 << Local MAC address bridge side (Sorry about the spaces.. .otherwise github turns : cd : into a CD icon) 1 8c:bf:a6:b6:ec:49 no 28.70 1 9c:5c:8e:16:16:24 no 0.00 5 a2:3f:31:a5:70:da yes 0.00 1 b8:26:6c:59:9e:80 no 0.10 3 da:8f:3c:7b:8d:5b yes 0.00 1 f8:0d:60:d5:2a:55 no 20.14

My VM/SP IP Stack says :

PCCA3 device ENT0: PCCA reports home hardware address 8242CD90D30B for link EN0

(That's the tap0 MAC address +1)

(So the MAC address.. or SOME sort of MAC address is properly brought back up)

** However....

After issuing a "tcpdump -e -i tap0 -n arp" I get :

PING 192.168.1.130 (192.168.1.130) 56(84) bytes of data. 15:37:30.304353 00:0c:29:f8:e3:4e > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.1.130 tell 192.168.1.21, length 28 (It's a broadcast frame.. So it's normal every port will receive it - except the transmitting port) 15:37:30.305392 00:00:00:00:00:00 > 00:0c:29:f8:e3:4e, ethertype ARP (0x0806), length 60: Reply 192.168.1.130 is-at 82:42:cd:90:d3:0b, length 46 (There is a reply. So the frame with the ARP request did make it to the IP stack, and the IP stack replied)

It's the 00:00:00:00:00:00 I am worried about... If I tcpdump on the bridge side, the response never shows (which would make sense... the linux bridge/vswitch probably blocks this non-sense source MAC address). The MAC address 82:42:CD:90:D3:0B also doesn't show on "brctl showmac br0" (so the linux bridge/vswitch didn't receive anything pertaining to that MAC address).

Granted, the IP stack probably should have inserted the source MAC address on the outbound frame... But I am wondering if an LCS implementation such as the 3172 running ICP wouldn't insert it itself - and wondering whether the LCS code may have to insert it (if it is not present).

--Ivan

jphartmann commented 7 years ago

Ivan, it is rather annoying that you quote the text that is right above; I can see it a lot better formatted in the issue. Itself, but if you insist on quoting, quote the entire issue so far.

Did you forget to tell us whether this is Windos or UNIX. I think you did not, though "tcpdump" might be your clue. If it is Windows, I shall bow out here.

As part of my L/390 I wrote a Linux kernel ethernet device driver (creating a network interface that you can see with ifconfig). I supports a subchannel that has a CTC device as seen from the userland side. It takes an Ethernet frame from userland and adds it to the interface queue. I provide no MAC addresses anywhere, so the Linux kernel must be smart enough to look at the frame type and do the required ARP and insert the target MAC. Presumably the source MAC is not added until the packet is put on the wire. I do call eth_type_trans, but my third edition Linux Device Drivers does not describe this and the description in the second edition is for receiving packets, so I'm afraid that is so far as I can get.

It is a bit hazy now fifteen years later, so I have appended the code for the open part of the device manager; you will find the ethernet stuff at the bottom. Now before you start calling me a bungling idiot, do remember this is kernel code.

Well, github does not allow me to. I shall send you the file direct; anyone else please drop me a line.

ivan-w commented 7 years ago

I do quote because I do not use the github interface but usually reply using the e-mail interface (and used the Mailing list etiquette). My apologies for replying as such, I will refrain from doing so henceforth.

The 'brctl' commands issued and such (since no such utility exists under windows) should have been hint enough. But, yes, it is under linux (Debian Jessy).

What I am talking about the is the specifics about ctc_lcs.c (The LCS implementation or 3172 ICP emulation) - It is simply writing to the TAP (not TUN) device and only takes it as-is, as an ethernet passthrough.

Somewhere in ctc_lcs.c, the packet is being written to the tap device (whatever the ethertype.. IP, ARP, RARP, SNA) . It is ALWAYS an ethernet/Layer2 frame (Or TR - not supported)... But the driver assumes the underlying IP layer did fill the hardware MAC address - but I am thinking some IP layers may assume the LCS/3172/ICP layer will fill in that part on an IP or ARP frame.

Linux Tap will NOT add the source MAC address (there is always a possibility that the underlying stack is also a virtual switch - think QDIO + z/VM Vswitch + z/VM TCPIP | Virtual machines connected to the CP VSWITCH - so it relies on the one writing to the TAP has set a MAC address on its own).

However, LCS is a different story. It is a 1 point only Interface to Switch (Unless there is a promiscuous mode ?). So I assume a 3172 running ICP would fill in the blanks.

--Ivan

jphartmann commented 7 years ago

Before I start philosophizing, let me understand you, Ivan. You ran tcpdump on the sending system, right? If so, could you try tcpdump on the receiving system? I speculate that the adapter might have added its MAC before putting the packet on the wire.

ivan-w commented 7 years ago

John,

The ping is between the GUEST (running under hercules) and the host system (the linux system running hercules).

The setup is as follows :

VM/SP5 FAL (TCP/IP) -> LCS(hercules) -> tap0 -> Bridge (br0) -> Linux

tcpdump on the tap0 shows the frame with a zeroed out source MAC address for the ARP reply. tcpdump on the br0 interface shows no inbound frame (the br0 is where the interface is defined on the linux side).

This works just fine with qeth/qdio, but not with LCS when the IP stack of the OS running under hercules doesn't fill in the source MAC address it has retrieved via the LAN Info pseudo frame.

Also, unfortunately, the VM/SP 5 FAL(IP) stack doesn't support QETH.

My guess (but it's only a guess) is that the LCS driver should set the source MAC address on the outgoing frame if it is zeroe'd out on output.

I am not sure how a 3172 running ICP wouldn't add the source MAC address on an outgoing frame in such a case.

--Ivan

jphartmann commented 7 years ago

Would it be useful to know what happens when the ping gets to a real hardware adapter going to another PC?

ivan-w commented 7 years ago

What do you mean by - to a real adapter ?

I can only bind a LCS to a TAP device (not any to any physical ethernet adapter)

--Ivan

ivan-w commented 7 years ago

Fish has provided a possible patch. And it works MUCH better.

Being tested..

mcisho commented 7 years ago

I was just attempting to reproduce your problem, and I cannot. This is what LCS traced for an ARP request coming out of the z/VM TCPIP virtual machine (I've removed the times and message numbers):- 0:1D41 LCS: Accept data of size 66 bytes from guest LCS: data: +0000< 00400100 FFFFFFFF FFFFC4D6 C71D4081 .@............@. . ........DOG. a LCS: data: +0010< 08060001 08000604 0001C4D6 C71D4081 ..............@. ..........DOG. a LCS: data: +0020< C0A801E6 00000000 0000C0A8 01CE6066 ..............`f {y.W......{y..-. LCS: data: +0030< 17AEEAC8 716461C3 07D72202 A3738B02 ....qda..."..s.. ...H../C.P..t... As you can see the source MAC address is filled in.

Have you done a Hercules traces that shows the MAC as zero? Or have you only traced at the host level? What does Fish's fix do?

ivan-w commented 7 years ago

For LCS :

The problem is not the inbound frame !

The problem is the outbound frame. The ARP broadcast is received alright, but the ARP reply has a ALL Zeroes source MAC address.

The fix is filling the MAC address of the LCS port as the source MAC address if the source MAC address is all zeroes.

It works ;)

--Ivan

mcisho commented 7 years ago

Inbound & outbound? I considered outbound to be from the Hercules guest to the host, and vice versa for inbound. I guess it depends where you're looking from!

ivan-w commented 7 years ago

To me inbound is from the host to the guest.. Outbound from the guest to the host running hercules..

The scenario is as follows :

Host A : any host on the same LAN Host B : The IP Stack of the OS running on hercules

A pings B A sends an ARP request WHOAS : DST MAC Address - ff:ff:ff:ff:ff:ff (Inbound frame) B Receives the frame - Replies : ARP is-at <MAC address of B> : However - SRC MAC Address of Eth frame is : 00:00:00:00:00:00 (outbound frame)

Since the SRC MAC address is all Zeroes, the frame is dropped by any intervening switch (physical, virtual or bridge).

The fix fills the zeroes for the SRC MAC Address with the MAC Address of the LCS adapter.

The change is a ~10 lines fix.

diff --git a/ctc_lcs.c b/ctc_lcs.c index 478640e..2331c1f 100644 --- a/ctc_lcs.c +++ b/ctc_lcs.c @@ -924,6 +924,7 @@ void LCS_Write( DEVBLK* pDEVBLK, U32 sCount, char cPktType[8]; char buf[32]; U16 hwEthernetType;

*** FIX COURTESY OF FISH

--Ivan

mcisho commented 7 years ago

Let me get this clear. Your z/VM TCPIP virtual machine is sending out an ARP reply with a source MAC address of zero? All ARP replies? Only ARP replies, all other frames are OK? I am completely unable to reproduce the behaviour with my VM.

ivan-w commented 7 years ago

No.. It's occuring on a VM/SP 5 system running the FAL stack.

--Ivan

ivan-w commented 7 years ago

Committed 9a97cf63e4f862dd19c994861bbcd2d22f96a5ed

ivan-w commented 7 years ago

Tested here and fixes the issue. Will close in 24h unless the issue is causing other problems.

Fish-Git commented 7 years ago

@ivan-w I think your fix (commit 9a97cf63e4f862dd19c994861bbcd2d22f96a5ed) needs fixing! :)

diff -r -a -x .git -x 'msvc.AMD64.*' -x 'msvc.dllmod.*' -x 'msvc.debug.*' -x '*.suo' -x '*.ncb' -x '*.user' -x '*.htm' -x WORK -x DICTS -x FILES -x 'allTests.*' -x '*.rej' -x '*.orig' -Nu hercules-1/ctc_lcs.c hercules-0/ctc_lcs.c
--- hercules-1/ctc_lcs.c    2017-03-25 08:31:41.886145700 -0700
+++ hercules-0/ctc_lcs.c    2017-03-25 08:39:00.543564300 -0700
@@ -1092,7 +1092,13 @@
             {
                 PLCSPORT  pLCSPORT  = &pLCSDEV->pLCSBLK->Port[ pLCSDEV->bPort ];
                 memcpy( pEthFrame->bSrcMAC, pLCSPORT->MAC_Address, sizeof( MAC ));
+
+#if !defined(OPTION_TUNTAP_LCS_SAME_ADDR)
+                /* Respond with a different MAC address for the LCS side */
+                /* unless the TAP mechanism is designed as such          */
+                /* cf : hostopts.h for an explanation                    */
                 pEthFrame->bSrcMAC[5]++;   /* Get next MAC address */
+#endif
             }

             // Trace Ethernet frame before sending to TAP device

. Refer to the code at the very end of the LCS_LanStats() function which is already doing the same thing, and which, interestingly enough, was added by you way back in 2011! :)

ivan-w commented 7 years ago

I don't remember ever meddling with the LCS code ever... (not saying I didn't, just that I can't remember doing that)

However,

Would that do ?

diff --git a/ctc_lcs.c b/ctc_lcs.c index 2331c1f..9bea258 100644 --- a/ctc_lcs.c +++ b/ctc_lcs.c @@ -1092,7 +1092,9 @@ void LCS_Write( DEVBLK pDEVBLK, U32 sCount, { PLCSPORT pLCSPORT = &pLCSDEV->pLCSBLK->Port[ pLCSDEV->bPort ]; memcpy( pEthFrame->bSrcMAC, pLCSPORT->MAC_Address, sizeof( MAC )); +#if !defined(OPTION_TUNTAP_LCS_SAME_ADDR) pEthFrame->bSrcMAC[5]++; / Get next MAC address */ +#endif }

         // Trace Ethernet frame before sending to TAP device

--Ivan

ivan-w commented 7 years ago

Added check of whether OPTION_TUNTAP_LCS_SAME_ADDR is set by commit 0f46a9239deed00e112a0a21d2e4b230b02ef0c9

ivan-w commented 7 years ago

Closing issue - everything now works as expected

Justinpalakkattel commented 5 years ago

Hai i am using java app i have to activate it by mac id i cant access mac id from ubuntu or debian what can i do?