Skip to content
Snippets Groups Projects
Commit ce94a86f authored by Jan David Mol's avatar Jan David Mol Committed by Reinder Kraaij
Browse files

Resolve COB-328 "Multicast destinations"

parent 6847e053
No related branches found
No related tags found
1 merge request!1093Resolve COB-328 "Multicast destinations"
...@@ -103,15 +103,18 @@ render_CDB_environment_ilt: ...@@ -103,15 +103,18 @@ render_CDB_environment_ilt:
python -m pip install . python -m pip install .
# fetch IPs from netbox (netbox.astron.nl) # fetch IPs from netbox (netbox.astron.nl)
curl -X GET -k 'https://10.87.2.131/api/ipam/ip-addresses/?dns_name__isw=lcu-&limit=100' -H 'Accept: application/json' -H "Authorization: Token ${NETBOX_TOKEN}" > netbox.json curl -X GET -k 'https://10.87.2.131/api/ipam/ip-addresses/?dns_name__isw=lcu-&limit=100' -H 'Accept: application/json' -H "Authorization: Token ${NETBOX_TOKEN}" > netbox-lcu-ips.json
curl -X GET -k 'https://10.87.2.131/api/ipam/prefixes/?description__ic=multicast%20range' -H 'accept: application/json' -H "Authorization: Token ${NETBOX_TOKEN}" > netbox-data-networks.json
mkdir -p generated/CDB/environments mkdir -p generated/CDB/environments
for STATION in ${LOFAR2_STATIONS}; do for STATION in ${LOFAR2_STATIONS}; do
LCU_IP=`jq < netbox.json '.results[] | select(.dns_name == "lcu-'${STATION}'.data.lofar.eu") | .address | split("/") | .[0]' -r` LCU_IP=`jq < netbox-lcu-ips.json '.results[] | select(.dns_name == "lcu-'${STATION}'.data.lofar.eu") | .address | split("/") | .[0]' -r`
echo "Generating CDB for ${STATION} using LCU IP ${LCU_IP}" DATA_NETWORK=`jq < netbox-data-networks.json '.results[] | select(.description | test("'${STATION}' multicast range"; "i")) | .prefix' -r`
l2ss-generate-cdb-datastreams -s ${STATION} -l ${LCU_IP} > generated/CDB/environments/${STATION}-ilt.json
echo "Generating CDB for ${STATION} using LCU IP ${LCU_IP} DATA NETWORK ${DATA_NETWORK}"
l2ss-generate-cdb-datastreams -s ${STATION} -l ${LCU_IP} -d ${DATA_NETWORK} > generated/CDB/environments/${STATION}-ilt.json
done done
artifacts: artifacts:
expire_in: 4 weeks expire_in: 4 weeks
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Copyright (C) 2025 ASTRON (Netherlands Institute for Radio Astronomy) # Copyright (C) 2025 ASTRON (Netherlands Institute for Radio Astronomy)
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
from ipaddress import IPv4Address from ipaddress import IPv4Address, IPv4Network
from typing import Dict, List from typing import Dict, List
from tangostationcontrol.toolkit._cdb import CDB from tangostationcontrol.toolkit._cdb import CDB
...@@ -10,10 +10,22 @@ from tangostationcontrol.toolkit._cdb import CDB ...@@ -10,10 +10,22 @@ from tangostationcontrol.toolkit._cdb import CDB
N_pol = 2 N_pol = 2
def multicast_mac(multicast_ip: IPv4Address) -> str:
"""Compute the Multicast destination MAC address from its IP address"""
# see f.e. https://technet.microsoft.com/en-us/library/cc957928.aspx
lower_23bits = int(multicast_ip) & 0x7FF
lower_hex = f"{lower_23bits:06x}"
return f"01:00:5e:{lower_hex[0:2]}:{lower_hex[2:4]}:{lower_hex[4:6]}"
class StationData: class StationData:
def __init__(self, station, lcu_ip: IPv4Address, resolver=None): def __init__(
self, station, lcu_ip: IPv4Address, data_network: IPv4Network, resolver=None
):
self.station = station self.station = station
self.lcu_ip = lcu_ip self.lcu_ip = lcu_ip
self.data_network = data_network
@property @property
def station_nr(self) -> int: def station_nr(self) -> int:
...@@ -41,7 +53,15 @@ class StationData: ...@@ -41,7 +53,15 @@ class StationData:
# using the 00:22:86 prefix, see https://maclookup.app/vendors/astron # using the 00:22:86 prefix, see https://maclookup.app/vendors/astron
return f"00:22:86:{self.station_8bit_id:02x}:{antenna_field_idx:02x}:{fpga_nr // 4:01}{fpga_nr % 4:01}" return f"00:22:86:{self.station_8bit_id:02x}:{antenna_field_idx:02x}:{fpga_nr // 4:01}{fpga_nr % 4:01}"
def _fpga_source_ip(self, antenna_field: str, fpga_nr: int): def _fpga_source_ip(self, antenna_field: str, fpga_nr: int) -> IPv4Address:
raise NotImplementedError
def _beamlet_destination_ip(
self, antenna_field: str, stream_nr: int
) -> IPv4Address:
raise NotImplementedError
def _beamlet_destination_port(self, antenna_field: str, stream_nr: int) -> int:
raise NotImplementedError raise NotImplementedError
def properties_Beamlet(self, antenna_field: str) -> Dict[str, List[str]]: def properties_Beamlet(self, antenna_field: str) -> Dict[str, List[str]]:
...@@ -55,12 +75,16 @@ class StationData: ...@@ -55,12 +75,16 @@ class StationData:
"FPGA_beamlet_output_hdr_udp_source_port_RW_default": [ "FPGA_beamlet_output_hdr_udp_source_port_RW_default": [
50000 + n for n in range(16) 50000 + n for n in range(16)
], ],
# "FPGA_beamlet_output_multiple_hdr_eth_destination_mac_RW_default_shorthand": [ "FPGA_beamlet_output_multiple_hdr_eth_destination_mac_RW_default_shorthand": [
# ], multicast_mac(self._beamlet_destination_ip(antenna_field, n))
# "FPGA_beamlet_output_multiple_hdr_ip_destination_address_RW_default_shorthand": [ for n in range(4)
# ], ],
# "FPGA_beamlet_output_multiple_hdr_udp_destination_port_RW_default_shorthand": [ "FPGA_beamlet_output_multiple_hdr_ip_destination_address_RW_default_shorthand": [
# ], self._beamlet_destination_ip(antenna_field, n) for n in range(4)
],
"FPGA_beamlet_output_multiple_hdr_udp_destination_port_RW_default_shorthand": [
self._beamlet_destination_port(antenna_field, n) for n in range(4)
],
} }
def CDB(self) -> CDB: def CDB(self) -> CDB:
...@@ -73,7 +97,7 @@ class CSStationData(StationData): ...@@ -73,7 +97,7 @@ class CSStationData(StationData):
def antenna_fields(self) -> list[str]: def antenna_fields(self) -> list[str]:
return ["LBA", "HBA0", "HBA1"] return ["LBA", "HBA0", "HBA1"]
def _fpga_source_ip(self, antenna_field: str, fpga_nr: int): def _fpga_source_ip(self, antenna_field: str, fpga_nr: int) -> IPv4Address:
# defined as per IP plan # defined as per IP plan
match antenna_field: match antenna_field:
case "LBA": case "LBA":
...@@ -85,6 +109,27 @@ class CSStationData(StationData): ...@@ -85,6 +109,27 @@ class CSStationData(StationData):
raise ValueError(f"Unknown antenna field: {antenna_field}") raise ValueError(f"Unknown antenna field: {antenna_field}")
def _beamlet_destination_ip(
self, antenna_field: str, stream_nr: int
) -> IPv4Address:
# defined as per IP plan
match antenna_field:
case "LBA":
return list(self.data_network.hosts())[0 + stream_nr]
case "HBA0":
return list(self.data_network.hosts())[32 + stream_nr]
case "HBA1":
return list(self.data_network.hosts())[64 + stream_nr]
def _beamlet_destination_port(self, antenna_field: str, stream_nr: int) -> int:
match antenna_field:
case "LBA":
return 10000 + stream_nr
case "HBA0":
return 10100 + stream_nr
case "HBA1":
return 10200 + stream_nr
def CDB(self) -> CDB: def CDB(self) -> CDB:
cdb = super().CDB() cdb = super().CDB()
cdb.add_device_properties( cdb.add_device_properties(
...@@ -104,7 +149,7 @@ class RSStationData(StationData): ...@@ -104,7 +149,7 @@ class RSStationData(StationData):
def antenna_fields(self) -> list[str]: def antenna_fields(self) -> list[str]:
return ["LBA", "HBA"] return ["LBA", "HBA"]
def _fpga_source_ip(self, antenna_field: str, fpga_nr: int): def _fpga_source_ip(self, antenna_field: str, fpga_nr: int) -> IPv4Address:
# defined as per IP plan # defined as per IP plan
match antenna_field: match antenna_field:
case "LBA": case "LBA":
...@@ -114,6 +159,23 @@ class RSStationData(StationData): ...@@ -114,6 +159,23 @@ class RSStationData(StationData):
raise ValueError(f"Unknown antenna field: {antenna_field}") raise ValueError(f"Unknown antenna field: {antenna_field}")
def _beamlet_destination_ip(
self, antenna_field: str, stream_nr: int
) -> IPv4Address:
# defined as per IP plan
match antenna_field:
case "LBA":
return list(self.data_network.hosts())[0 + stream_nr]
case "HBA":
return list(self.data_network.hosts())[32 + stream_nr]
def _beamlet_destination_port(self, antenna_field: str, stream_nr: int) -> int:
match antenna_field:
case "LBA":
return 10000 + stream_nr
case "HBA":
return 10100 + stream_nr
def CDB(self) -> CDB: def CDB(self) -> CDB:
cdb = super().CDB() cdb = super().CDB()
cdb.add_device_properties( cdb.add_device_properties(
...@@ -156,10 +218,17 @@ def main(**kwargs): ...@@ -156,10 +218,17 @@ def main(**kwargs):
required=True, required=True,
help="LCU IP for this station", help="LCU IP for this station",
) )
parser.add_argument(
"-d",
"--data-network",
type=IPv4Network,
required=True,
help="IP range for FPGA data stream destinations",
)
args = parser.parse_args() args = parser.parse_args()
station_data = StationDataFactory(args.station, args.lcu_ip) station_data = StationDataFactory(args.station, args.lcu_ip, args.data_network)
print(str(station_data.CDB())) print(str(station_data.CDB()))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment