The future is already here. GS UK 2025

I was at the GS UK conference recently (which was bigger than ever) and learned so many new things.

I’ll give some short descriptions of what I learned. There is no order to these topics. Some items come in more than one area.

  • Python is very popular and widely used.
    • pyracf for issuing RACF commands from OMVS
    • pysdsf accessing SDSF from OMVS (z/OS 3.2)
  • Use ssh to access z/OS instead of ISPF
    • Many Unixy commands ported to z/OS through zopen project
    • /dfds to access data sets
    • Possibly faster than through ISPF
  • vscode is the most commonly used IDE with lots of plugins. Can edit z/OS data sets, files, submit jobs and look at spool – via Zowe
    • Git is the standard repository
    • Edit in vscode
    • check-in to Git
    • on z/os pull from Git
    • compile and run from ssh window
    • can edit on your workstation and process on z/OS
    • use Zowe/vscode to edit datasets and files in vscode, submit JCL and look at the spool. Can use zowe command line interface for issuing stuff to z/OS ( eg list files, issue operator commands)
  • People like my blog posts – Wow ! I never really knew. If you like/use anyone’s post please “like it” so the author knows. If it has been really helpful make a comment “I found this very useful”. Steven P. pointed out that you need o be logged on to a WordPress account to be able to “like” or raise a comment – this would explain why I got so few likes!
  • Lots of capturing data and displaying it in tools like grafana.
    • Python used to capture data
  • Monitoring dashboards are so last year.
    • Now have modern tools (AI) to detect changes from historical data, then alert people to differences, who then use the dashboards.
  • SDSF version 3.2 can intercept RACF writes to SMF and can display the activity, so if RACF is configured you can display OK access to resources. You just get the failures reported on syslog
  • You’ve been hacked
    • Often there is evidence months before hack – you just need to spot it
      • Pat is a z/OS sysprog who comes to work, has a coffee and starts working at 0930. Today there were two password validation failures at 0430. Is this unusual – yes. Do something
      • The password failures occurred at 0925 and 0926 – is this unusual.. you might want to check
      • You had a connection from an IP address you’ve never seen before – what do you do? Slow down their traffic and notify someone
    • Prepare for this
      • Have an integrated playbook.
        • Populate panels with the suspicious userid, and have a pull down to disable. It takes longer to type data into a RACF command than use from pre populated fields. (Eg userid COLIN Click here to disable it. )
        • Have people use the play book so they know what to do when an incident occurs. You do not have time to learn as you go along.
      • You have minutes to act. Getting someone out of bed is too long.
    • What software is running where? File Integrity Monitoring
      • I thought this was module ABC CSECT CS123 PTF level UK987654. No. If someone has zapped the module how do you know? And when did they do it? This helps you know how far you need to restore from,
      • Take each module and CSECT and create an encrypted checksum for each component. Store the information system id/library/module/CSECT/hash code. Check it weekly If someone has zapped the module – it will have a different hash. You can also see which systems are back level.
      • Do the same for configuration files eg parmlib.
      • If it has changed there should be a matching change request.
  • Regulations are in. If you have hacker insurance you will have to comply with regulation standards- such as
    • have you implemented File Integrity Monitoring (above).
    • Do you follow the standards for isolation of responsibilities.
    • “Yes” is the wrong answer. You need to demonstrate proof.
      • eg password strength. You need tests to validate it
      • prove this TCPIP connection is encrypted
  • Certificates should be reissued every 30-60 days. Not the n years it used to be.
  • OpenTelemetry tracing system. Configure applications and subsystems, to emit “here I am” to central monitoring to show path transaction took. Eg MQ client, into CICS transaction… to another CICS and back. Can do it for all – or just a sample of some requests.

  • Lots of youngster involved with z/OS.
  • Lots of old familiar faces who love working with z/OS, and should have retired years ago . This includes me (grin).

The Like box below only works if you are logged on to wordPress.

You should be able to click on the stars and give a score without logging on

Go back

Your message has been sent

Rating(required)
Warning

Performance: My works run slower on pre-production than in test – why?

I was at the 2025 GSUK, and someone asked me this (amongst other questions). I had a think about it and came up with….

The unhelpful answer

Well it is obvious; what did you expect?

A better answer.

There are many reasons…. and some are not obvious.

General performance concepts

  • A piece of work is either using CPU or waiting.

CPU

  • Work can use CPU
  • A transaction may be delayed from starting. For example WLM says other work is more important that yours.
  • Once your transaction has started, and has issued a requests, such as an I/O request. When the request has finished – your task may not be re-dispatched immediately because other work has a higher priority – other work is dispatched to keep to the WLM system goals.

I remember going to a presentation about WLM when it was first available. Customers were “complaining” because batch work was going through faster when WLM was enabled. CICS transactions used to complete in half a second, but the requirement was 1 second. The transactions now take 1 second (no one noticed) – and batch is doing more work.

Your transaction may be doing more work.

For example in Pre Production, you only read one record from the (small) database. The Production database may be much larger, and the data is not in memory. This means it takes longer to get a record. In production, you may have to process more records – which adds to the amount of work done.

Your database may not be optimally configured. In one customer incident, a table was (mis) configured so it did a sequential scan of up to 100 records to find the required record. In production there were 1000’s of records to scan to find the required record; increasing the processing time by a factor of 10. They defined an index and cured the problem. The problem only showed up in production.

Waiting

There are many reason for an application to wait. For example

For CPU

See above.

Latches

A latch is a serialisation mechanism for very short duration activities (microseconds). For example if a thread wants to GETMAIN a block of storage, the system gets the address space latch (lock), updates the few storage pointers, and releases the latch. The more thread running in the address space, and the more storage requests they issue the more chance of two threads trying to get the latch at the same time and so tasks may have to wait. At the deep hardware level the storage may have to be accessed from different CPUs… and so data moves 1 meter or so, and so this is a slow access.

Application IO

An application can read/write a record from a data set, a file, or the spool. There may be serialisation to the resource to ensure only one thread can use the record.

Also if there are a limited number of connections from the processor to the disk controller, higher priority work may be scheduled before your work.

Database logging delays

If your application is using DB2, IMS, or MQ, these subsystems process requests from many address spaces and multiple threads.

As part of transactional work, data is written to the log buffers.

At commit time, the data for the thread is written out to disk. Once the data is written successfully the commit can return.

There are several situations.

  • If the data has already been written – do not wait; just return “OK”
  • There is no log I/O active in the subsystem. Start the I/O and wait for completion. The duration is one I/O.
  • There is currently an I/O in progress. Keep writing data to a buffer. When the I/O completes, start the next I/O with data from the buffer. On average your task waits half an I/O time while the previous I/O completes, then the I/O time. The duration (on average) is 1.5 I/O time
  • As the system gets busier more data is written in each I/O. This means each I/O takes longer – and the previous wait takes longer.
  • There is so much data in the log buffer, that several log writes are needed before the last of your data is successfully written. The duration is multiple long I/O rquests.

This means that other jobs running on the system, using the same DB2, IMS or MQ will impact the time to write the data to the subsystem log, and so impact your job.

Database record delays

If you have two threads wanting to update the same database record, then there will be a data lock from the time gets the record for update, to the end of the commit time. Another task wanting that record will have to wait for the first task to finish. Of course on a busy system, the commits will take longer, as described above.

What can make it worse is when a transactions gets a record for update (so locking it) and then issues a remote request, for example over TCPIP, to another server. The record lock is held for the duration of this request, and the commit etc. The time depends on the network and back end system.

Network traffic

If your transaction is using remote servers, this can take a significant time

  • Establishing a connection to the remote server.
  • Establishing the TLS session. This can take 3 flows to establish a secure session.
  • Transferring the data. This may involve several blocks of data sent, and several blocks received.
  • Big blocks of data can take longer to process. You can configure the network to use big buffers.
  • The network traffic depends on all users of the network, so you may have production data going to the remote site. On the Pre Production you may have a local, closer, server.

Waiting for the human input.

For example prompting for account number and name.

Yes, but the pre-production is not busy!

This is where you have to step back and look at the bigger picture.

Typically the physical CPU is partitioned into many LPARS. You may have 2 production LPARS, and one pre-production LPARs.
The box has been configured so that production gets priority over Pre Production.

CPU

Although your work is top of the queue for execution on your LPAR , the LPAR is not given any CPU because the production LPARs have priority. When the production LPARs do not need CPU, the Pre Production gets to use the CPU and your work runs (or not depending on other work)

IO

There may be no other task on your LPAR using the device, so there is no delays in the LPAR issuing the I/O request to the disk controller. However other work may be running on other LPARs, and so there is contention from the storage controller down to the storage.

Overall

So not such an obvious answer after all!

Please give a rating.

Go back

Your message has been sent

Please give rating for the blog post(optional – no logon required)
Warning

Where the heck is TCPIP.DATA?

I’ve been struggling to get a TCPIP function working. The TCPIP documentation repeatedly says use the configuration in TCPIP.DATA. I did – and it made no difference.

What it should say is in the //SYSTCPD data set in your TCPIP procedure.

TCPIP started tasks such as the resolver, can query TCPIP and get the name of the dataset.

As I’ve said before, it is easy when you know the answer.
I also blogged this, so when I forget this in a few months time, and look for TCPIP.DATA , a search of the internet will find it.

Ahh TCPIP redirect solved my routing problem

I was trying to go from z/OS running on zD&T system on a Linux server to the external internet. It was very frustrating in that a ping to a site would not work, I made an adjustment, ping still didn’t work, I made another adjustment, and then it worked. I then undid the adjustments and it worked! I optimised this by doing 3 pings – the first two failed, then it worked.
If I re-ipled – it worked. If I shutdown, and restarted the Linux server – it failed the same way.

My configuration

I had the default for IPV4 going to address 192.168.1.22. This was the value of the connection if I used FIND_IO or ip addr.

What I saw was

  1. Source 192.168.1.25 -> 151…. this did not work ( no response )
  2. Source 192.168.1.25 -> 151…. this did not work ( no response)
  3. Source 192.168.1.22 Redirect ICMP request gateway 192.168.1.254.
    • src 192.168.1.25 -> 151… worked

What was happening was my request with IP address 192.168.1.25 was being routed (because of my routing definitions) to 192.168.1.22. I don’t know if the request ever got out of my Wireless router, or the site I was pinging was unable to send a response back. After the second of these incidents the “router” with address 192.168.1.22 send a redirect message to my original node saying instead of sending me the traffic – send it directly to address 192.168.1.254 which is my wireless router’s address.

I changed the routing to be 192.168.1.254 – and next time I restarted my server, and reipled z/OS, I could ping and it worked every time.

Lesson learned

I learned that it is important to get the right definitions.

I also learned that making a change, and when you undo the change, you do not always get back to the original state.

Understanding BT Smart hub 2 and my IPv6 addresses

As part of some work trying to get IPV6 to connect, I spent too much time understanding the various IP addresses in my configuration. By accident I found the magic incantation that allowed my z/OS on zD&T to talk to the outside internet.

Under the covers the BT Smart Hub 2 has a router called Arcadyan_ae. You will see this in a Wireshark trace. My IP addresses start with 2A00:23C5:… This belongs to BT. I’ve replace the address with BT:a:b:c .

This Blog post is referred to in Connecting a zPDT z/OS to the internet to using IPV6 and explains the various IPv6 addresses

My BT Smart Hub 2

You can display configuration information from the Smart Hub by using a web browser and address 192.168.1.254.

The Smart Hub IPv6 information.

This is password protected in the Advanced Settings.

There is a section IPv6 WAN details, this was not of interest.
The section IPv6 LAN details has

  • Link local address: fe80::6a2:22ff:feae:2871/64

For my Linux Server

the information in the BT Hub was

  • Device Name: Colins Server
  • Device Icon: None
  • Connection Status: Connected
  • IP address: 192.168.1.25 I think this came from my z/OS system running on the server!
  • MAC address: CC:64…:C5
  • Connection Type: Wireless
  • Address assignment: DHCP
  • Always using this address: YES
  • IPv6 Addressing:
    • GUA(Temporary): BT:a:b:c:2f3d:acdb Assigned by device
    • GUA (Permanent) :BT:a:b:c:7cd3:8993 Assigned by device
    • Link local address:fe80::…:8c80:37a4 Assigned by device

The IPv4 address (192.168.1.25) varied from day to day. During the day, it tended to be the same value. I could not find what caused it to change.

On my Linux server

The command ip addr gave

wlxcc641aee92c5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
link/ether cc:64:1a...:c5 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.25/24 brd 192.168.1.255 scope global dynamic noprefixroute wlxcc641aee92c5
...
inet6 BT:a:b:c:7cd3:8993/64 scope global temporary dynamic
...
inet6 BT:a:b:c:2f3d:acdb/64 scope global dynamic mngtmpaddr noprefixroute
...
inet6 fe80::...:8c80:37a4 /64 scope link noprefixroute
...

Where

  • the GUA (Permanent) is the same as the address with scope global temporary dynamic
  • the GUA (Temporary) is the same as the address with scope global dynamic mngtmpaddr noprefixroute
  • the Link local address is the same as the address with scope link noprefixroute. The word link gives it away.

Configure z/OS TCPIP Interface

I configured the interface like

 INTERFACE WIRE6 
DEFINE IPAQENET6
CHPIDTYPE OSD
IPADDR 2001:DB7:8::1
PORTNAME PORTB

INTERFACE WIRE6
ADDADDR BT:a:b:c::1
START WIRE6

This interface has addresses 2001:DB7:8::1 and BT:a:b:c::1. The value BT:a:b:c is the same as the high part of the Smart Hub’s Global unicast address: BT:a:b:c:6a2:22ff:feae:2871. The value BT:a:b:cuniquely identifies my Smart Hub2 router. Any device in the subarea below this router, must have the same top part. I picked address 1(::1).

The TSO NETSTAT HOME command gave

IntfName:   WIRE6 
Address: 2001:db7:8::1
Type: Global
Flags:
Address: BT:a:b:c::1
Type: Global
Flags:
Address: fe80::cc64:1a02:ee:92c5
Type: Link_Local
Flags: Autoconfigured

With the two addresses I configured, and an internally generated link local address.

The TSO NETSTAT ND gave

Query Neighbor cache for fe80::6a2:22ff:feae:2871 
IntfName: WIRE6 IntfType: IPAQENET6
LinkLayerAddr: 04A222AE2871 State: Reachable
Type: Router AdvDfltRtr: Yes

Where fe80::6a2:22ff:feae:2871 is the IPv6 address of the router – see the top of this blog post.

Routing

My routing table did not need an IPv6 default entry because TCPIP can deduce it.

BEGINRoutes 
; Destination SubnetMask FirstHop LinkName Size
ROUTE 10.0.0.0 255.0.0.0 = TAP0 MTU 1492

ROUTE DEFAULT 192.168.1.254 WIRE MTU 1492

ENDRoutes

TSO NETSTAT ROUTE gave me

IPv6 Destinations 
DestIP: Default
Gw: fe80::6a2:22ff:feae:2871
Intf: WIRE6 Refcnt: 0000000000
Flgs: UGD MTU: 1492
MTU: 65535
DestIP: 2001:db7:8::1/128
Gw: ::
Intf: WIRE6 Refcnt: 0000000000
Flgs: UH MTU: 1492
DestIP: BT:a:b:c::/64
Gw: ::
Intf: WIRE6 Refcnt: 0000000000
Flgs: UD MTU: 1492
DestIP: aBT:a:b:c::1/128
Gw: ::
Intf: WIRE6 Refcnt: 0000000000
Flgs: UH MTU: 1492
DestIP: fe80::cc64:1a02:ee:92c5/128
Gw: ::
Intf: WIRE6 Refcnt: 0000000000
Flgs: UH MTU: 1492

DestIP: ::1/128
Gw: ::
Intf: LOOPBACK6 Refcnt: 0000000000
Flgs: UH

Where the Default is the value in TSO NETSTAT ND, and is the IP address of the Smart Hub2 – see above.

PING

When I did a TCPIP PING to an IPv6 address,

  • the source was BT:a:b:c::1
  • the destination was 2a04:abcd::81

The first ping

The first ping had the following flows

  1. Ping the address
  2. The router does not know where the originating IP address came from, so it asks all devices connected to it – Does anyone have this IP address?
  3. Z/OS replies to the router saying “I’ve got that address”
  4. The router says “Here is some data for you

In more technically

  1. From BT:a:b:c::1 ping destination 2a04:abcd::81
  2. (From the router) Source Address: fe80::6a2:22ff:feae:2871 to all devices on the subnet (ff02::1:ff00:1) Neighbour Solicitation for BT:a:b:c::1
  3. (From z/OS) Source Address: fe80::cc64:1a03:ee:92c5 to the router (fe80::6a2:22ff:feae:2871) Neighbour Advertisement BT:a:b:c::1
  4. From 2a04:abcd::81 to BT:a:b:c :1 ping response


The second ping request went directly to z/OS because the BT Hub had learned where the IP address was.

Connecting a zPDT z/OS to the internet to using IPV6

I needed to get my ZD&T machine connected to the internet so it could download some files as part of an install. Note, this allows my z/OS to contact the internet, externals machines cannot contact my machine.

I blogged

It took a while to get it working. It is based on scenario 4 of the zD&T documentation.

The configuration uses the wireless connection from my Linux server.

You need to know/configure the address of various end points. Some addresses are configured by the systems, some addresses you need to configure.

Before you start

You need to know what the IP address of your z/OS image is

I used the GUA permanent address

   INTERFACE WIRE6 
DEFINE IPAQENET6
CHPIDTYPE OSD

IPADDR 2001:DB7:8::1
PORTNAME PORTB

INTERFACE WIRE6
ADDADDR BT:a:b:c:B8CE:404B:3360:3644
START WIRE6

What’s my TCP configuration on Linux?

The command ip addr gave (displaying only the IP V6 entries)

1: lo: <LOOPBACK,UP,LOWER_UP> ...    
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: eno1:...
...
inet6 fe80::2d8:61ff:fee9:312a/64 scope link ...
3: wlxcc641aee92c5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...

inet6 BT:a:b:c:8b43:7ce6:34d1:c0fe/64 scope global temporary dynamic ...

inet6 BT:a:b:c:9824:30b:2f3d:acdb/64 scope global dynamic mngtmpaddr noprefixroute ...
inet6 fe80::7bfc:5da1:8c80:37a4/64 scope link noprefixroute ...
4: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc ...
link/ether ...
...
inet6 fe80::48f6:deff:fef4:c8d4/64 scope link valid_lft forever preferred_lft forever

Where

  • lo is the loop back address.
  • eno1 is the connection over an Ethernet cable to my laptop
  • wlxcc641aee92c5 is the wireless connection to my router and the outside world. The IP address of the Linux server end is BT:a:b:c… . This value is used in the z/OS configuration.
  • tap0 is the tunnel interface to z/OS from the base linux machine. It has address fe80::48f6:deff:fef4:c8d4 This address is internal to the subnet.

I think these end point addresses were all generated for me.

My devmap

The devmap file contains the definitions of the emulated devices. For the OSA I had

[manager]  # tap0 define network adapter (OSA) for communication with Linux
name awsosa 0009 --path=A0 --pathtype=OSD --tunnel_intf=y # QDIO mode
device 400 osa osa --unitadd=0
device 401 osa osa --unitadd=1
device 402 osa osa --unitadd=2

name awsosa 0010 --path=F1 --pathtype=OSD --interface=wlxcc641aee92c5
device 404 osa osa --unitadd=0
device 405 osa osa --unitadd=1
device 406 osa osa --unitadd=2
device 407 osa osa --unitadd=3
device 408 osa osa --unitadd=4
device 409 osa osa --unitadd=5

Where the –interface is the same name as my wireless interface (see above).

Find_io

The find_io command gives the network configuration known by the emulation code.

FIND_IO for "colin@colin-ThinkCentre-M920s" 
Interface Current MAC IPv4 IPv6
Path Name State Addr Addr Address
---- ---------------- ----------- ---- ------ --------------
F0 eno1 UP,RUNNING 00... 10.... fe80::2d8:61ff:fee9:312a%eno1
F1 wlxcc641aee92c5 UP,RUNNING cc... 192.... BT:a:b:c:8b43:7ce6:34d1:c0fe

We have the same information as the ip addr command

The OSAs

In the devmap file the OSAs were defined as starting at 400 and 404. They each use 3 “wires”. One for reading, one for writing, and one for data (addresses 400, 401 and 402).

[manager]  # tap0 define network adapter (OSA) for communication with Linux
name awsosa 0009 --path=A0 --pathtype=OSD --tunnel_intf=y # QDIO mode
device 400 osa osa --unitadd=0
device 401 osa osa --unitadd=1
device 402 osa osa --unitadd=2
device 403 osa osa --unitadd=3


name awsosa 0010 --path=F1 --pathtype=OSD --interface=wlxcc641aee92c5
device 404 osa osa --unitadd=0
device 405 osa osa --unitadd=1
device 406 osa osa --unitadd=2
device 407 osa osa --unitadd=3
device 408 osa osa --unitadd=4
device 409 osa osa --unitadd=5
device 40a osa osa --unitadd=6

Where wlxcc641aee92c5 is the name of the wireless interface on Linux.

In the z/OS file ADCD.Z31B.VTAMLST(OSATRL2) is

OSATRL1 VBUILD TYPE=TRL                                                 
OSATRL1E TRLE LNCTL=MPC,READ=(0400),WRITE=(0401),DATAPATH=(0402), X
PORTNAME=PORTA, X
MPCLEVEL=QDIO
OSATRL2E TRLE LNCTL=MPC,READ=(0404),WRITE=(0405),DATAPATH=(0406,407), X
PORTNAME=PORTB, X
MPCLEVEL=QDIO

Where we have the same addresses 400 and 404.
You refer to these definitions using PORTA and PORTB.

PORTB uses data paths 0406 for the TCPIP IPv4 inerface, and 0407 for the IPv6 Interface.

You can use the VTAM command D NET,TRL to display the status of them

          d net,trl                                         
STC05323 IST097I DISPLAY ACCEPTED
STC05323 IST350I DISPLAY TYPE = TRL
------------------------------------------------------------
TRL MAJOR NODE = ISTTRL
TRLE = IUTIQDIO STATUS = NEVAC CONTROL = MPC
TRLE = IUTSAMEH STATUS = NEVAC CONTROL = MPC
2 TRLE(S) DISPLAYED
------------------------------------------------------------
TRL MAJOR NODE = OSATRL2
TRLE = OSATRL1E STATUS = ACTIV CONTROL = MPC
TRLE = OSATRL2E STATUS = ACTIV CONTROL = MPC

Define the TCP/IP interfaces

Current levels of TCP define interfaces with the “INTERFACE” statement. DEVICE and LINK statements are deprecated.

My wireless definitions ar

                                                
INTERFACE WIRE
DEFINE IPAQENET
CHPIDTYPE OSD
IPADDR 192.168.1.61
PORTNAME PORTB
START WIRE

INTERFACE WIRE6
DEFINE IPAQENET6
CHPIDTYPE OSD
IPADDR BT:a:b:c::2
PORTNAME PORTB
; INTERFACE WIRE6
; ADDADDR BT:a:b:c::1

START WIRE6

This defines both IPv4 and IPv6 interfaces, both using the same port PORTB

The interfaces are started

I chose these two addresses myself. These address show up in the NETSTAT HOME command.

After it has started

The TSO NETSTAT HOME command gave

Home address list: 
LinkName: LOOPBACK
Address: 127.0.0.1
Flags:
IntfName: TAP0
Address: 10.1.1.2
Flags: Primary
IntfName: WIRE
Address: 192.168.1.61
Flags:
IntfName: WIRE6
Address: BT:a:b:c::2
Type: Global
Flags:
Address: fe80::cc64:1a02:ee:92c5
Type: Link_Local
Flags: Autoconfigured
IntfName: LOOPBACK6
Address: ::1
Type: Loopback
Flags:

Where we see the interfaces and their IP addresses.

Define the TCP Routes

I created COLIN.TCPPARMS(S5ROUTE) with content

BEGINRoutes 
; Destination SubnetMask FirstHop LinkName Size
ROUTE 10.0.0.0 255.0.0.0 10.1.1.1 TAP0 MTU 1492
; Default to the internet
ROUTE DEFAULT 192.168.1.254 WIRE MTU 1492
;ROUTE DEFAULT6 fe80::6a2:22ff:feae:2871 WIRE6 MTU 5000
ENDRoutes

Note there is no DEFAULT6 entry – TCPIP works this out for itself. If you have more than one IPv6 interface you should uncomment the DEFAULT6 statement to ensure the traffic goes the right way.

I used the TCPIP console command v tcpip,,obey,COLIN.TCPPARMS(S5ROUTE) to activate the routing table. If you get it wrong, edit the member, save the changes, and issue the command again.

The TSO NETSTAT ROUTE command gave me

IPv4 Destinations 
Destination Gateway Flags Refcnt Interface
----------- ------- ----- ------ ---------
Default 192.168.1.254 UGS 0000000000 WIRE
10.0.0.0/8 0.0.0.0 US 0000000000 TAP0
10.1.1.2/32 0.0.0.0 UH 0000000000 TAP0
127.0.0.1/32 0.0.0.0 UH 0000000000 LOOPBACK
192.168.1.61/32 0.0.0.0 UH 0000000000 WIRE
IPv6 Destinations
DestIP: Default
Gw: fe80::6a2:22ff:feae:2871
Intf: WIRE6 Refcnt: 0000000000
Flgs: UGD MTU: 1492
DestIP: ::1/128
Gw: ::
Intf: LOOPBACK6 Refcnt: 0000000000
Flgs: UH MTU: 65535
DestIP: BT:a:b:c::/64
Gw: ::
Intf: WIRE6 Refcnt: 0000000000
Flgs: UD MTU: 1492
DestIP: BT:a:b:c::2/128
Intf: WIRE6 Refcnt: 0000000000
Flgs: UH MTU: 1492
DestIP: fe80::cc64:1a02:ee:92c5/128
Gw: ::
Intf: WIRE6 Refcnt: 0000000000
Flgs: UH MTU: 1492

Where fe80::6a2:22ff:feae:2871 is from the BT Hub IPv6 LAN details: Link local address:.

The command TSO NETSTAT ND gives the neighbour discovery. This gave me

Query Neighbor cache for fe80::6a2:22ff:feae:2871 
IntfName: WIRE6 IntfType: IPAQENET6
LinkLayerAddr: 04A222AE2871 State: Reachable
Type: Router AdvDfltRtr: Yes

Which shows what IPv6 neighbours have been discovered.

And finally – test it

I could use the TSO PING command to ping a server the internet. Check you can ping the address from Linux before you try it from z/OS, because some servers do not respond to ping requests.

Doing a wireshark trace of a successful ping showed the originator IP address was BT:a:b:c::2, the home address of interface WIRE6 in TCPIP on my z/OS image.

Connecting a zPDT z/OS to the internet using IPv4

I needed to get my ZD&T machine connected to the internet so it could download some files as part of an install. Note, while this allows my z/OS to contact the internet, externals machines cannot contact my machine.

As a follow-on to this Blog post I wrote Connecting a zPDT z/OS to the internet to using IPV6 which extends this post.

As usual there are many strands to this, so I wrote Understanding BT home hub and my IPv6 addresses to cover some of the background knowledge.

It took a while to get it working. It is based on scenario 4 of the zD&T documentation.

The configuration uses the wireless connection from my Linux server.

You need to know/configure the address of various end points. Some addresses are configured by the systems, some addresses you need to configure.

What’s my TCP configuration on Linux?

The command ip addr gave (displaying only the IP V4 entries)

1: lo: <...> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever

2: eno1: <...> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:...
altname enp0s31f6
inet 10.1.0.3/24 brd 10.1.0.255 scope global eno1
valid_lft forever preferred_lft forever

3: wlxcc641aee92c5: <...> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether cc:...
inet 192.168.1.139/24 brd 192.168.1.255 scope global dynamic noprefixroute wlxcc641aee92c5
valid_lft 80179sec preferred_lft 80179sec
noprefixroute
valid_lft 263sec preferred_lft 83sec
inet6 fe80::7bfc:5da1:8c80:37a4/64 scope link noprefixroute
valid_lft forever preferred_lft forever
5: tap0: <...> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
link/ether 46:...
inet 10.1.1.1/24 brd 10.1.1.255 scope global tap0
valid_lft forever preferred_lft forever

Where

  • lo is the loop back address.
  • eno1 is the connection over an Ethernet cable to my laptop with the address (on this linux machine) 10.1.0.3. The address of the other end of the Ethernet, on my laptop, is 10.1.0.2
  • wlxcc641aee92c5 is the wireless connection to my router and the outside world. The IP address of the Linux server end is 192.168.1.139.
  • tap0 is the tunnel interface to z/OS from the base linux machine. It has address 10.1.1.1

I think these end point addresses were all generated for me.

Linux Settings

I believe that you need some Linux settings. Having repeated the scenario, it works even when the values described where set to 0, so the guidance in this section may not be relevant.

sysctl net.ipv4.ip_forward

to display the value. It needs to be 1. You can set it using

sudo sysctl -w net.ipv4.ip_forward=1
#sudo sysctl -w net.ipv6.conf.all.forwarding=1

You can do commands like

sysctl -a |grep v4
sysctl -a |grep v6

My devmap

The devmap file contains the definitions of the emulated devices. For the OSA I had

[manager]  # tap0 define network adapter (OSA) for communication with Linux
name awsosa 0009 --path=A0 --pathtype=OSD --tunnel_intf=y # QDIO mode
device 400 osa osa --unitadd=0
device 401 osa osa --unitadd=1
device 402 osa osa --unitadd=2

name awsosa 0010 --path=F1 --pathtype=OSD --interface=wlxcc641aee92c5
device 404 osa osa --unitadd=0
device 405 osa osa --unitadd=1
device 406 osa osa --unitadd=2
device 407 osa osa --unitadd=3
device 408 osa osa --unitadd=4
device 409 osa osa --unitadd=5

Where the –interface is the same name as my wireless interface (see above).

When I used IPv6 as well as IPv4, there were two TCPIP Interface on the same OSA. I need address 406 and 407 for one interface, and 408 and 409 for the other interface. The TCPIP documentation does not say this.

Find_io

The find_io command gives the network configuration known by the emulation code.

FIND_IO for "colin@colin-ThinkCentre-M920s" 

Interface Current MAC IPv4 IPv6
Path Name State Addr Address Address
------ ---------------- ---------------- ---- ------------- --------------
F0 eno1 UP, RUNNING 00:.. 10.1.0.3 fe80::...%eno1
F1 wlxcc641aee92c5 UP, RUNNING cc:.. 192.168.1.139 2a00:...
A0 tap0 UP, RUNNING 46:.. 10.1.1.1 fe80::...@tap0
...

End of FIND_IO

This is the same information as the ip addr command

The OSAs

In the devmap file the OSAs were defined as starting at 400 and 404. One for reading, one for writing, and several for data.

In the z/OS VTAM file ADCD.Z31B.VTAMLST(OSATRL2) (below) defines two OSAs.

The first is for my Ethernet. This has one TCPIP Interface, and so paths 402 and 403 for the data.

The second is for the wireless connection. This has two TCPIP interfaces one for IPV4 and one for IPv6. One uses path (406,407), the other uses(408,409). These addresses must match the devmap definitions.

OSATRL1 VBUILD TYPE=TRL                                                 
OSATRL1E TRLE LNCTL=MPC,READ=(0400),WRITE=(0401),DATAPATH=(0402), X
PORTNAME=PORTA, X
MPCLEVEL=QDIO
OSATRL2E TRLE LNCTL=MPC,READ=(0404),WRITE=(0405),DATAPATH=(0406,407), X
PORTNAME=PORTB, X
MPCLEVEL=QDIO


You refer to these definitions using PORTA and PORTB in the TCPIP interfaces

You can use the VTAM command D NET,TRL to display the status of them

          d net,trl                                         
STC05323 IST097I DISPLAY ACCEPTED
STC05323 IST350I DISPLAY TYPE = TRL
------------------------------------------------------------
TRL MAJOR NODE = ISTTRL
TRLE = IUTIQDIO STATUS = NEVAC CONTROL = MPC
TRLE = IUTSAMEH STATUS = NEVAC CONTROL = MPC
2 TRLE(S) DISPLAYED
------------------------------------------------------------
TRL MAJOR NODE = OSATRL2
TRLE = OSATRL1E STATUS = ACTIV CONTROL = MPC
TRLE = OSATRL2E STATUS = ACTIV CONTROL = MPC

Define the TCP/IP interfaces

Current levels of TCP define interfaces with the “INTERFACE” statement. DEVICE and LINK statements are deprecated.

My definitions for IPv4 are

 INTERFACE TAP0 
DEFINE IPAQENET
CHPIDTYPE OSD
IPADDR 10.1.1.2
PORTNAME PORTA
START TAP0

INTERFACE WIRE
DEFINE IPAQENET
CHPIDTYPE OSD
IPADDR 192.168.1.61
PRIROUTER
PORTNAME PORTB
START WIRE

This defines an interface TAP0 using the PORTA definitions above, and gives the z/OS end of the connection the address 10.1.1.2. From my laptop I can ping 10.1.1.2, it gets routed to the Linux server, and into z/OS.

The interface is started

Another interface WIRE is defined using PORTB and the z/OS end of the connection is 192.168.1.61

I chose these two addresses myself. These address show up in the NETSTAT HOME command.

After it has started

The TSO NETSTAT HOME command gave

MVS TCP/IP NETSTAT CS 3.1     
Home address list:
LinkName: LOOPBACK
Address: 127.0.0.1
Flags:
IntfName: TAP0
Address: 10.1.1.2
Flags: Primary
IntfName: WIRE
Address: 192.168.1.61
Flags:

Where we see the interfaces and their IP addresses.

Define the TCP Routes

I created COLIN.TCPPARMS(S5ROUTE) with content

BEGINRoutes 
; Destination SubnetMask FirstHop LinkName Size
ROUTE 10.0.0.0 255.0.0.0 10.1.1.1 TAP0 MTU 1492
ROUTE 192.168.1.0 255.255.255.0 = WIRE MTU 1492
ROUTE DEFAULT 192.168.1.254 WIRE MTU 1492
ENDRoutes

This says for the destination IP address if it is

  • anything beginning with 10. (from the subnet mask 255.0.0.0) send it over interface TAP0. The command ip addr shows tap0 with inet 10.1.1.1/24 brd 10.1.1.255
  • anything with address 192.168.1.something (from the subnet mask 255.255.255.0) sent it over interface WIRE (note: in this case this definition is redundant because of the default below).
  • anything else, send it down the DEFAULT definition over interface WIRE. The IP address of my wireless router is 192.168.1.254. Initially I had a different address – the address in the find_io. After several pings which timed out, ping worked. It is better to specify the address of the router/hub.

I used the TCPIP console command v tcpip,,obey,COLIN.TCPPARMS(S5ROUTE) to activate the routing table. If you get it wrong, edit the member, save the changes, and issue the command again.

The TSO NETSTAT ROUTE command gave me

IPv4 Destinations 
Destination Gateway Flags Refcnt Interface
----------- ------- ----- ------ ---------
Default 192.168.1.254 UGS 0000000000 WIRE
10.0.0.0/8 0.0.0.0 US 0000000000 TAP0
10.1.1.2/32 0.0.0.0 UH 0000000000 TAP0
127.0.0.1/32 0.0.0.0 UH 0000000000 LOOPBACK
192.168.1.61/32 0.0.0.0 UH 0000000000 WIRE

And finally – test it

I could use the TSO PING command to ping a server the internet. Check you can ping the address from Linux before you try it from z/OS, because some servers do not respond to ping requests.

Useful commands

On Linux

  • ip addr
  • ip route

On z/OS

VTAM operator commands
  • D NET,TRL
  • d net,trl,trle=OSATRL2E This gives information such as which OSA data ports are being used, by with TCPIP interfaces.
  • D NET,ID=…
  • D NET,ID=…,E
  • V NET,ACT,ID=….
  • V NET,INACT,ID=….
TCPIP operator commands
  • v tcpip,,obey,… for example COLIN.TCPPARMS(S5ROUTE)

TSO commands

  • TSO NETSTAT HOME
  • TSO NETSTAT ROUTE
  • TSO PING x.x.x.x
  • TSO TRACERTE x.x.x.x

Some problems I experienced

A ping did not get a response back

A wireshark trace of the wireless interface showed the ping request had an originator IP address of 10.1.1.2. This was caused by having the wrong routing table

MVS TCP/IP NETSTAT CS 3.1       TCPIP Name: TCPIP           17:10:28 
IPv4 Destinations
Destination Gateway Flags Refcnt Interface
----------- ------- ----- ------ ---------
Default 10.1.1.1 UGS 0000000000 TAP0
10.0.0.0/8 0.0.0.0 US 0000000000 TAP0
10.1.0.0/24 10.1.1.1 UGS 0000000000 TAP0
10.1.1.2/32 0.0.0.0 UH 0000000000 TAP0
127.0.0.1/32 0.0.0.0 UH 0000000000 LOOPBACK
192.168.1.61/32 0.0.0.0 UH 0000000000 WIRE

The default routing was via TAP0

The NETSTAT HOME gave

 MVS TCP/IP NETSTAT CS 3.1       TCPIP Name: TCPIP       
Home address list:
LinkName: LOOPBACK
Address: 127.0.0.1
Flags:
IntfName: TAP0
Address: 10.1.1.2
Flags: Primary
IntfName: WIRE
Address: 192.168.1.61
Flags:

So the IP address of the TAP0 interface was 10.1.1.2, and this was used as the originating end point.

Any nodes on the route to the destination do not know where 10.1.12 is located …. 10.*.*.* it is usually an address on the local machine, and so you get no response back.

With the address 192.168.1.xx the wireless router converts it to the router’s own address, and so the intermediate nodes on the journey can use the hub’s IP address, and the reply gets back to the wireless router.

Ping failed – nothing in wireshark

  INTERFACE WIRE 
DEFINE IPAQENET
CHPIDTYPE OSD
IPADDR 192.168.1.60
PRIROUTER
VLANID 2
PORTNAME PORTB

I had VLANID 2 … when I removed this statement it worked.

Sessions failed to start

When I started TCPIP I got the message

EZZ4336I ERROR DURING ACTIVATION OF INTERFACE WIRE – CODE 8010002A DIAGNOSTIC CODE 02

Using the command D U,,,400,8 showed

UNIT TYPE STATUS        VOLSER     VOLSTATE      SS  
0400 OSA A-BSY 0
0401 OSA A 0
0402 OSA A-BSY 0
0403 OSA O 0
0404 OSA OFFLINE 0
0405 OSA OFFLINE 0
0406 OSA OFFLINE 0
0407 OSA OFFLINE 0

This shows the second OSA was not available (it was offline). I found I had misconfigured the OSA with addresses (404, 405, and 406) in my devmap.

Not for humans but for search engines – Comms server

Below are messages I’ve experienced and my solutions

IST1578I DEVICE INOP DETECTED FOR … BY ISTTSCMA CODE = 104

and

EZZ4338I ERROR REPORTED ON INTERFACE … – CODE 80100040
DIAGNOSTIC CODE 03

I was trying to get IPV4 and IPV6 interfaces to work with one OSA.

With

OSATRL1 VBUILD TYPE=TRL 
OSATRL2E TRLE LNCTL=MPC,READ=(0404),WRITE=(0405),DATAPATH=(0406,407), X
PORTNAME=PORTB, X
PORTNUM=1, X
MPCLEVEL=QDIO

it produced the above messages

with

OSATRL1 VBUILD TYPE=TRL 
OSATRL2E TRLE LNCTL=MPC,READ=(0404),WRITE=(0405),DATAPATH=(0406,408), X
PORTNAME=PORTB, X
PORTNUM=1, X
MPCLEVEL=QDIO

so with two paths 406 and 408, instead of 406 and 407, it worked!

My zD&T devmap had

name awsosa 0010 --path=F1 --pathtype=OSD  --interface=wlxcc641aee92c5 
device 404 osa osa --unitadd=0
device 405 osa osa --unitadd=1
device 406 osa osa --unitadd=2
device 407 osa osa --unitadd=3
device 408 osa osa --unitadd=4
device 409 osa osa --unitadd=5
device 40a osa osa --unitadd=6

Where wlxcc641aee92c5 is my Linux wireless interface.
find_io gave me

         Interface         Current    MAC         IPv4          IPv6           
Path Name State Address Address Address
------ ---------------- ---------- ---------- ----------- --------------
...
F1 wlxcc641aee92c5 UP, RUNNING cc:64:... 192.168.1.61 2a00:23c5:...

Using ISMF and looking at volumes

The ISMF ISPF dialogs provide a good way of displaying information about SMS,volumes data sets etc.

Like many tools – it is easy once you know how to use it.

Where is there free disk space?

Using the ISMF dialogs (as a storage administrator)

                  ISMF PRIMARY OPTION MENU - z/OS DFSMS 3.1       
Selection or Command ===>


0 ISMF Profile - Specify ISMF User Profile
1 Data Set - Perform Functions Against Data Sets
2 Volume - Perform Functions Against Volumes

Option 2 Volume –>, 1 for DASD

                          VOLUME SELECTION ENTRY PANEL              Page 1 of 3
Command ===>

Select Source to Generate Volume List . . 2 (1 - Saved list, 2 - New list)
1 Generate from a Saved List Query Name To
List Name . . COLIN Save or Retrieve
2 Generate a New List from Criteria Below
Specify Source of the New List . . 1 (1 - Physical, 2 - SMS)
Optionally Specify One or More:
Enter "/" to select option Generate Exclusive list
Type of Volume List . . . 1 (1-Online,2-Not Online,3-Either)
Volume Serial Number . . USER* (fully or partially specified)
Device Type . . . . . . . (fully or partially specified)
Device Number . . . . . . (fully specified)
To Device Number . . . (for range of devices)
Acquire Physical Data . . Y (Y or N)
Acquire Space Data . . . Y (Y or N)
Storage Group Name . . . * (fully or partially specified)
CDS Name . . . . . . . 'ACTIVE'

Where Acquire Physical Data obtains

  • Device type such as 3390-3
  • Device number such as 0a94
  • Shared DASD such as YES
  • Use Attributes such as PRIV

and Acquire Space Data obtains and calculates

  • Free space
  • Free extents,
  • % Free index status
  • Allocated space
  • Free DSCBs
  • Fragmentation Index
  • Free VIRs (VTOC Index Records)
  • Largest extent
  • Physical status

gave

                                                           VOLUME LIST           
Command ===> Scroll ===> HALF
Entries 1-8 of 8
Enter Line Operators below: Data Columns 3-8 of 45

LINE VOLUME FREE % ALLOC FRAG LARGEST FREE
OPERATOR SERIAL SPACE FREE SPACE INDEX EXTENT EXTENTS
---(1)---- -(2)-- ---(3)--- (4)- ---(5)--- -(6)- ---(7)--- --(8)--
USER00 81233K 1 8233268K 674 6308K 135
USER02 100822K 4 2670678K 252 53953K 31
USER03 5202K 0 2766298K 483 2213K 9
USER04 1457936K 53 1313564K 49 1328284K 20
USER05 78577K 3 2692923K 83 63802K 4
USER06 289020K 10 2482480K 179 105581K 16
USER07 500735K 18 2270765K 92 356142K 11
USER08 953881K 34 1817619K 86 509478K 3
---------- ------ ----------- BOTTOM OF DATA ----------- ------ ----

If you press PF1 for help, press “enter to continue” and select option 6 Data Column Descriptions it gives all of the columns names. They have a name and number.

Back in the data display, you can scroll sideways to display these field.

You can use the command view 3,23 to display just those fields, or view * to display all of the fields.

You can use view save name and view select name to save the current view configuration as name.

I could not find a way of displaying all of the attributes for a volume in a vertical list.

Sort

You can say sort 3 to sort by column 3 ascending, or just sort where you can specify the columns and ascending or descending.

The columns you can sort by depend on what are displayed via the view command.

How difficult is it to delete a data set – it can be harder than you think.

I was using a volume on one zD&T system, and used the same volume on the next version of zD&T. Some of the datasets are SMS managed, and were cataloged in the first system’s master catalog.

Now I’m on the latest level of zD&T, I am trying to delete unwanted data sets, and this was a challenge, as all of the usual methods did not work.

I can use ISPF 3.4 and specify the volume USER05. There are some old datasets, such as SYS1.S0W1.Z24C.DMP00001. These are not cataloged. They are only visible in ISPF 3.4 if you specify the volume. If you try to browse the data set it gives data set not cataloged.

I failed to delete the dataset using the usual techniques….

From ISPF

If you try to delete it from ISPF 3.4 it says “Data set not cataloged”,

From JCL

For example

//IBMDEL   JOB 1,MSGCLASS=H 
//TSO EXEC PGM=IEFBR14
//DDS DD DSN=SYS1.S0W1.Z24C.DMP00001,VOL=SER=USER05,
// DISP=(OLD,DELETE)
/*

This fails with the error message

IEFA107I IBMDEL TSO DDS – DATA SET SYS1.S0W1.Z24C.DMP00001 NOT FOUND

From IDCAMS

//IBMDEL2  JOB 
//STEP1 EXEC PGM=IDCAMS
//DD1 DD VOL=SER=USER05,UNIT=3390,DISP=OLD
//* DSN=SYS1.S0W1.Z24C.DMP00003
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
DELETE -
SYS1.S0W1.Z24C.DMP00001 -
FILE (DD1) -
PURGE
/*

Fails with

IDC3012I ENTRY SYS1.S0W1.Z24C.DMP00001 NOT FOUND
IDC3009I ** VSAM CATALOG RETURN CODE IS 8 – REASON CODE IS IGG0CLEG-42

The problem…

The dataset is on an SMS managed volume. All data sets managed by SMS have to be cataloged. The catalog that owns the dataset is on a non existant system – the old master catalog from the system from 3 years ago. The outcome is that there is no catalog available to locate the data set.

On the SMS volume USER05 is the SMS dataset SYS1.VVDS.VUSER05. This is like a catalog for the volume, and contains information about all the data sets on the SMS volume. You can use IDCAMS to print this data set (in hex).

The solution…

You need to recatalog it – then delete it

recatalog

//IBMRECAT JOB 
//RECATSMS EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DEFINE NONVSAM(NAME(SYS1.S0W1.Z24C.DMP00001 ) -
OWNER(COLIN ) -
VOLUMES(USER05) -
DEVT(3390 ) -
RECATALOG)
LISTCAT ENT(SYS1.S0W1.Z24C.DMP00001) ALL
/*

This gave

  DEFINE NONVSAM(NAME(SYS1.S0W1.Z24C.DMP00001   ) -                                           
OWNER(COLIN ) -
VOLUMES(USER05) -
DEVT(3390 ) -
RECATALOG)
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

LISTCAT ENT(SYS1.S0W1.Z24C.DMP00001) ALL
NONVSAM ------- SYS1.S0W1.Z24C.DMP00001
IN-CAT --- CATALOG.Z31B.MASTER
HISTORY
DATASET-OWNER------COLIN CREATION--------2025.296
RELEASE----------------2 EXPIRATION------0000.000
ACCOUNT-INFO-----------------------------------(NULL)
SMSDATA
STORAGECLASS -----SCBASE MANAGEMENTCLASS---(NULL)
DATACLASS --------(NULL) LBACKUP ---0000.000.0000
ENCRYPTIONDATA
DATA SET ENCRYPTION-----(NO)
VOLUMES
VOLSER------------USER05 DEVTYPE------X'3010200F' FSEQN------------------0
ASSOCIATIONS--------(NULL)
ATTRIBUTES

Having done this, I can now browse SYS1.S0W1.Z24C.DMP00001 in ISPF without specifying a volume, so proving it is now cataloged.

Delete it

If I now try to delete it I get

IEC331I 050-088(,USER05),COLIN,ISPFPROC,VCMP,IGG0CLE4
IEC614I SCRATCH FAILED – RC 008, DIAGNOSTIC INFORMATION IS (040942D1),
ISPFPROC,USER05,SYS1.S0W1.Z24C.DMP00001

The codes for IEC331I are given in IEC3009I. If you search for “code 50” then page down till you get code 88, it says

Explanation: A VVR or NVR with the correct component name was found, but the catalog name did not match. On a delete request, the BCS record will be deleted, but the VVR or NVR and the format 1 DSCB will not be scratched. There is no SFI data.

I had to use

//IBMDEL2  JOB 
//STEP1 EXEC PGM=IDCAMS
//DD1 DD VOL=SER=USER05,UNIT=3390,DISP=OLD
//SYSPRINT DD SYSOUT=A
//SYSIN DD *
DELETE SYS1.S0W1.Z24C.DMP00001 NVR FILE(DD1)
/*

Which says delete the data set (and remove it from the VVDS dataset).
This job was successful, and the data set was no longer on the volume.

Sometimes I had to remove the NVR from the delete statement.
My overall JCL was

//IBMDEL   JOB  1 
//E1 EXPORT SYMLIST=*
// SET NAME='IZUSVR.JVM.IZUSVR1.D250809.T080903.X001'
// SET VOL='USER06'
//RECATSMS EXEC PGM=IDCAMS
//DD1 DD VOL=SER=&VOL,UNIT=3390,DISP=OLD
//SYSPRINT DD SYSOUT=*
//SYSIN DD *,SYMBOLS=JCLONLY

DEFINE NONVSAM(NAME(&NAME.) -
OWNER(COLIN ) -
VOLUMES(&VOL.) -
DEVT(3390 ) -
RECATALOG)

LISTCAT ENT(&NAME. ) ALL

DELETE &NAME. NVR FILE(DD1)

DELETE &NAME. FILE(DD1)
/*