Loading go-apps/meep-simu5g-bridge/bridge.go +23 −3 Changes for go-apps/meep-simu5g-bridge/bridge.go: 23 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -67,8 +67,8 @@ func NewBridgeInstance(cfg *bridge.IntegrationConfig) (*BridgeInstance, error) { _ = tun.Close() return nil, err } log.Info("Bridge connected to simulator host S at ", cfg.BridgeTCPAddr(), " (sandbox host B, scenario=", cfg.Deployment.ScenarioID, ")") log.Info("Bridge connected to Network simulation stack at ", cfg.BridgeTCPAddr(), " (EdgeNative-Connector, scenario=", cfg.Deployment.ScenarioID, ")") return b, nil } Loading Loading @@ -180,11 +180,17 @@ func (b *BridgeInstance) loopTunToSocket(ctx context.Context) error { } pkt := buf[:n] ueID := uint16(0) if src := ipv4Source(pkt); src != nil { src := ipv4Source(pkt) if src != nil { if idx := b.cfg.ResolveUeIndexFromIP(src); idx >= 0 { ueID = uint16(idx) } } if proto := ipv4Proto(pkt); proto == 1 { log.Info("TUN UL ICMP bytes=", n, " src=", src, " dst=", ipv4Dest(pkt), " ueId=", ueID) } else { log.Debug("TUN UL bytes=", n, " proto=", proto, " src=", src, " dst=", ipv4Dest(pkt), " ueId=", ueID) } frame := bridge.EncodeDataULFrame(ueID, pkt, 0) b.mutex.Lock() conn := b.conn Loading Loading @@ -260,3 +266,17 @@ func ipv4Source(pkt []byte) net.IP { } return net.IP(pkt[12:16]).To4() } func ipv4Dest(pkt []byte) net.IP { if len(pkt) < 20 || pkt[0]>>4 != 4 { return nil } return net.IP(pkt[16:20]).To4() } func ipv4Proto(pkt []byte) uint8 { if len(pkt) < 10 || pkt[0]>>4 != 4 { return 0 } return pkt[9] } go-packages/meep-nw-simu-catalog/instance.go +2 −2 Changes for go-packages/meep-nw-simu-catalog/instance.go: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ import ( ) /** Default sim_time_limit sent when CreateInstanceRequest.SimTimeLimit is empty. */ const DefaultSimTimeLimit = "300s" const DefaultSimTimeLimit = "1800s" // Half an hour /** * @brief POST /v1/instances request body. Loading Loading @@ -208,7 +208,7 @@ func (c *Client) DeleteInstance(ctx context.Context, sandboxID string, retainArt path := c.cfg.NemURL + "/v1/instances/" + url.PathEscape(sandboxID) if retainArtifacts { path += "?retain_artifacts=true" path += "?retain_artifacts=false" } raw, status, err := c.doInstance(ctx, http.MethodDelete, path, nil) if err != nil { Loading tools/simu5g/install-simu5g-routes-sandbox.sh +114 −16 Changes for tools/simu5g/install-simu5g-routes-sandbox.sh: 114 added lines, 16 removed lines. Original line number Diff line number Diff line #!/usr/bin/env bash # install-simu5g-routes-sandbox.sh — Discover UE/MEC PodIPs from a sandbox namespace # by pod name, then delegate to install-simu5g-routes.sh (unchanged). # by pod name, then delegate to install-simu5g-routes.sh (policy routes + SIMU5G iptables). # # Classification (among scenario pods): # MEC — pod name starts with MEC_NAME_PREFIX (default: mep) # UE — all other scenario pods with a PodIP # # Run apply after a user activates a network scenario (PodIPs exist). Do not run # this from the Calico dataplane switch — that happens before any sandbox exists. # # The derived selectors are informational (kubectl -l cannot express name prefixes); # this script resolves PodIPs and passes UE_CIDRS / MEC_CIDRS to the base installer. # Loading @@ -32,8 +35,8 @@ CONFIG_FILE="${CONFIG_FILE:-${SCRIPT_DIR}/example-integration-config.json}" # Host routing / TUN (same defaults as install-simu5g-routes.sh) TUN_DEV="${TUN_DEV:-simu5g-br0}" TUN_ADDR="${TUN_ADDR:-169.254.250.1/32}" CNI_DEV="${CNI_DEV:-weave}" POD_CIDR="${POD_CIDR:-10.32.0.0/12}" CNI_DEV="${CNI_DEV:-}" POD_CIDR="${POD_CIDR:-}" MGMT_DEV="${MGMT_DEV:-ens160}" UPLINK_ONLY="${UPLINK_ONLY:-0}" STATE_DIR="${STATE_DIR:-/var/lib/simu5g-routes}" Loading @@ -43,6 +46,10 @@ UE_POD_SELECTOR="" MEC_POD_SELECTOR="" UE_CIDRS="" MEC_CIDRS="" mec_names=() ue_names=() mec_ips=() ue_ips=() log() { printf '[%s] %s\n' "$SCRIPT_NAME" "$*"; } die() { log "ERROR: $*"; exit 1; } Loading @@ -51,6 +58,21 @@ require_root() { [[ "${EUID:-$(id -u)}" -eq 0 ]] || die "run as root (sudo $SCRIPT_NAME $*)" } # sudo resets HOME to /root, so kubectl would miss the operator's cluster. # Prefer SUDO_USER's kubeconfig unless KUBECONFIG was set explicitly. resolve_kube_identity() { local sudo_home if [[ "${EUID:-$(id -u)}" -eq 0 && -n "${SUDO_USER:-}" && "$SUDO_USER" != "root" ]]; then sudo_home="$(getent passwd "$SUDO_USER" | cut -d: -f6)" if [[ -z "${KUBECONFIG:-}" && -n "$sudo_home" && -f "${sudo_home}/.kube/config" ]]; then export KUBECONFIG="${sudo_home}/.kube/config" log "sudo: using ${SUDO_USER} kubeconfig ${KUBECONFIG}" fi fi command -v "$KUBECTL" >/dev/null 2>&1 || die "kubectl not found (PATH=$PATH)" log "kubectl=$(command -v "$KUBECTL") KUBECONFIG=${KUBECONFIG:-<default $HOME/.kube/config>} context=$("$KUBECTL" config current-context 2>/dev/null || echo '<none>')" } # Create and bring up the bridge TUN (mirrors install-simu5g-routes.sh setup_tun). setup_tun() { if ! ip link show "$TUN_DEV" >/dev/null 2>&1; then Loading Loading @@ -84,15 +106,16 @@ Options (environment or flags): -n, --namespace NS Sandbox namespace (default: ${SANDBOX_NS}) --scenario-selector S kubectl -l filter before name split (default: ${SCENARIO_SELECTOR}) --mec-prefix P MEC pod name prefix (default: ${MEC_NAME_PREFIX}) --config-file PATH Passed to install-simu5g-routes.sh (default: example-integration-config.json) --config-file PATH Passed to install-simu5g-routes.sh; also rewrites sandboxIpCidr from live PodIPs TUN / host routing (passed through to ${INSTALLER##*/}): TUN_DEV=$TUN_DEV TUN_ADDR=$TUN_ADDR CNI_DEV=$CNI_DEV Examples: $SCRIPT_NAME discover -n sbxvipkywt sudo $SCRIPT_NAME setup-tun sudo $SCRIPT_NAME apply -n sbxvipkywt $SCRIPT_NAME discover -n sbx4lesbpo --config-file ${SCRIPT_DIR}/monaco-harbor-integration-config.json sudo $SCRIPT_NAME apply -n sbx4lesbpo --config-file ${SCRIPT_DIR}/monaco-harbor-integration-config.json # apply: TUN + ip rule table 100 + SIMU5G-FORWARD/STEER iptables for live PodIPs # If sudo still sees 0 pods: sudo KUBECONFIG=\$HOME/.kube/config $SCRIPT_NAME apply ... sudo $SCRIPT_NAME status sudo $SCRIPT_NAME delete-tun sudo $SCRIPT_NAME rollback Loading @@ -103,6 +126,7 @@ EOF parse_args() { ACTION="" CONFIG_FILE_EXPLICIT=0 while [[ $# -gt 0 ]]; do case "$1" in discover|setup-tun|apply|status|rollback|delete-tun) Loading @@ -124,6 +148,7 @@ parse_args() { ;; --config-file) CONFIG_FILE="${2:?config path required}" CONFIG_FILE_EXPLICIT=1 shift 2 ;; -h|--help|help) Loading Loading @@ -155,9 +180,15 @@ pods_to_cidr_csv() { # List scenario pods: "name<TAB>ip" per line (portable jsonpath — no ?() filter). list_scenario_pods_with_selector() { local selector=$1 local out out="$("$KUBECTL" -n "$SANDBOX_NS" get pods -l "$selector" \ -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}' 2>/dev/null)" || return 1 local out err err="$(mktemp)" if ! out="$("$KUBECTL" -n "$SANDBOX_NS" get pods -l "$selector" \ -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}' 2>"$err")"; then log "WARN: kubectl get pods -l ${selector} failed: $(tr '\n' ' ' <"$err")" rm -f "$err" return 1 fi rm -f "$err" while IFS=$'\t' read -r name ip; do [[ -n "$name" && -n "$ip" ]] || continue printf '%s\t%s\n' "$name" "$ip" Loading @@ -172,24 +203,85 @@ list_scenario_pods() { tmp="$(mktemp)" list_scenario_pods_with_selector "$SCENARIO_SELECTOR" >"$tmp" || true rows=$(grep -c . "$tmp" 2>/dev/null || echo 0) rows=$(wc -l <"$tmp" | tr -d ' ') if [[ "$rows" -eq 0 ]]; then if [[ "${rows:-0}" -eq 0 ]]; then local fallback="meepSandbox=${SANDBOX_NS}" log "WARN: no pods for -l ${SCENARIO_SELECTOR}; trying fallback -l ${fallback}" list_scenario_pods_with_selector "$fallback" >"$tmp" || true rows=$(grep -c . "$tmp" 2>/dev/null || echo 0) rows=$(wc -l <"$tmp" | tr -d ' ') fi cat "$tmp" rm -f "$tmp" } # Rewrite ueMappings/mecEndpoints sandboxIpCidr in --config-file from live pod names. write_config_cidrs() { [[ "${CONFIG_FILE_EXPLICIT:-0}" == 1 ]] || return 0 [[ -f "$CONFIG_FILE" ]] || die "--config-file not found: $CONFIG_FILE" command -v python3 >/dev/null 2>&1 || die "python3 required to rewrite $CONFIG_FILE" local pairs tmp pairs="$(mktemp)" tmp="$(mktemp)" local i for i in "${!mec_names[@]}"; do printf '%s %s\n' "${mec_names[$i]}" "${mec_ips[$i]}" >>"$pairs" done for i in "${!ue_names[@]}"; do printf '%s %s\n' "${ue_names[$i]}" "${ue_ips[$i]}" >>"$pairs" done python3 - "$CONFIG_FILE" "$pairs" "$tmp" <<'PY' import json, pathlib, sys cfg_path, pairs_path, out_path = sys.argv[1], sys.argv[2], sys.argv[3] cfg = json.loads(pathlib.Path(cfg_path).read_text()) pods = [] for line in pathlib.Path(pairs_path).read_text().splitlines(): name, ip = line.split() pods.append((name, ip)) def match_ue(ueid, name): return name == ueid or name.startswith(ueid + "-") for mapping in cfg.get("ueMappings", []): ueid = mapping.get("ueId") or "" hits = [ip for name, ip in pods if match_ue(ueid, name)] if len(hits) == 1: mapping["sandboxIpCidr"] = hits[0] + "/32" elif len(hits) > 1: print(f"WARN: multiple pods for ueId={ueid}: {hits}", file=sys.stderr) else: print(f"WARN: no pod for ueId={ueid}", file=sys.stderr) mec_pods = [(n, ip) for n, ip in pods if n.startswith("mep")] for i, ep in enumerate(cfg.get("mecEndpoints", [])): eid = ep.get("endpointId") or "" hits = [ip for n, ip in mec_pods if n.startswith(eid)] if not hits and i < len(mec_pods): hits = [mec_pods[i][1]] if hits: ep["sandboxIpCidr"] = hits[0] + "/32" else: print(f"WARN: no MEC pod for endpointId={eid}", file=sys.stderr) pathlib.Path(out_path).write_text(json.dumps(cfg, indent=2) + "\n") PY mv "$tmp" "$CONFIG_FILE" chmod 644 "$CONFIG_FILE" 2>/dev/null || true if [[ -n "${SUDO_USER:-}" && "$SUDO_USER" != "root" ]]; then chown "${SUDO_USER}:" "$CONFIG_FILE" 2>/dev/null || true fi rm -f "$pairs" log "updated sandboxIpCidr in $CONFIG_FILE from live PodIPs" } discover_pod_groups() { command -v "$KUBECTL" >/dev/null 2>&1 || die "kubectl not found" local mec_names=() ue_names=() local mec_ips=() ue_ips=() mec_names=() ue_names=() mec_ips=() ue_ips=() while IFS=$'\t' read -r name ip; do [[ -n "$name" && -n "$ip" ]] || continue Loading Loading @@ -218,6 +310,9 @@ discover_pod_groups() { printf '%s\n' "MEC_CIDRS=${MEC_CIDRS:-<none>}" printf '%s\n' "UE_CIDRS=${UE_CIDRS:-<none>}" printf '%s\n' "TUN_DEV=${TUN_DEV} TUN_ADDR=${TUN_ADDR} (use setup-tun or apply to create)" if ip link show bpfin.cali >/dev/null 2>&1; then printf '%s\n' "CNI=Calico (per-pod cali* veths) — do not pass CNI_DEV=cali...; apply auto-detects" fi printf '\n%s\n' "TUN interface:" show_tun_status printf '\n%s\n' "MEC pods (${#mec_names[@]}):" Loading @@ -241,6 +336,7 @@ discover_pod_groups() { [[ -n "$MEC_CIDRS" ]] || die "no MEC pods (name prefix '${MEC_NAME_PREFIX}') in namespace ${SANDBOX_NS}" [[ -n "$UE_CIDRS" ]] || die "no UE pods (non-${MEC_NAME_PREFIX} scenario pods) in namespace ${SANDBOX_NS}" write_config_cidrs } run_installer() { Loading Loading @@ -276,6 +372,7 @@ cmd_delete_tun() { main() { parse_args "$@" resolve_kube_identity case "$ACTION" in discover) Loading @@ -289,7 +386,8 @@ main() { ;; apply) require_root apply discover_pod_groups >/dev/null # Do not redirect discover: errors (no pods) must be visible. TUN is created only after pods exist. discover_pod_groups log "MEC_POD_SELECTOR=${MEC_POD_SELECTOR}" log "UE_POD_SELECTOR=${UE_POD_SELECTOR}" log "MEC_CIDRS=${MEC_CIDRS}" Loading tools/simu5g/install-simu5g-routes.sh 0 → 100755 +646 −0 File added.Preview size limit exceeded, changes collapsed. Show changes tools/simu5g/monaco-harbor-integration-config.json +42 −10 Changes for tools/simu5g/monaco-harbor-integration-config.json: 42 added lines, 10 removed lines. Original line number Diff line number Diff line Loading @@ -29,19 +29,51 @@ "meAppInst": "monaco-harbor" }, "ueMappings": [ {"ueId": "ue-car-0", "sandboxIpCidr": "10.0.0.1/32", "simu5gModulePath": "MonacoHarbor.ue_car[0]"}, {"ueId": "ue-car-1", "sandboxIpCidr": "10.0.0.2/32", "simu5gModulePath": "MonacoHarbor.ue_car[1]"}, {"ueId": "ue-car-2", "sandboxIpCidr": "10.0.0.3/32", "simu5gModulePath": "MonacoHarbor.ue_car[2]"}, {"ueId": "ue-car-3", "sandboxIpCidr": "10.0.0.4/32", "simu5gModulePath": "MonacoHarbor.ue_car[3]"}, {"ueId": "ue-ped-0", "sandboxIpCidr": "10.0.0.11/32", "simu5gModulePath": "MonacoHarbor.ue_ped[0]"}, {"ueId": "ue-ped-1", "sandboxIpCidr": "10.0.0.12/32", "simu5gModulePath": "MonacoHarbor.ue_ped[1]"}, {"ueId": "ue-ped-2", "sandboxIpCidr": "10.0.0.13/32", "simu5gModulePath": "MonacoHarbor.ue_ped[2]"}, {"ueId": "ue-ped-3", "sandboxIpCidr": "10.0.0.14/32", "simu5gModulePath": "MonacoHarbor.ue_ped[3]"} { "ueId": "ue-car-0", "sandboxIpCidr": "192.168.108.147/32", "simu5gModulePath": "MonacoHarbor.ue_car[0]" }, { "ueId": "ue-car-1", "sandboxIpCidr": "192.168.108.185/32", "simu5gModulePath": "MonacoHarbor.ue_car[1]" }, { "ueId": "ue-car-2", "sandboxIpCidr": "192.168.108.180/32", "simu5gModulePath": "MonacoHarbor.ue_car[2]" }, { "ueId": "ue-car-3", "sandboxIpCidr": "192.168.108.150/32", "simu5gModulePath": "MonacoHarbor.ue_car[3]" }, { "ueId": "ue-ped-0", "sandboxIpCidr": "192.168.108.130/32", "simu5gModulePath": "MonacoHarbor.ue_ped[0]" }, { "ueId": "ue-ped-1", "sandboxIpCidr": "192.168.108.136/32", "simu5gModulePath": "MonacoHarbor.ue_ped[1]" }, { "ueId": "ue-ped-2", "sandboxIpCidr": "192.168.108.179/32", "simu5gModulePath": "MonacoHarbor.ue_ped[2]" }, { "ueId": "ue-ped-3", "sandboxIpCidr": "192.168.108.135/32", "simu5gModulePath": "MonacoHarbor.ue_ped[3]" } ], "mecEndpoints": [ { "endpointId": "mec1", "sandboxIpCidr": "10.20.0.0/24", "endpointId": "mep1", "sandboxIpCidr": "192.168.108.134/32", "simu5gModulePath": "router" } ], Loading Loading
go-apps/meep-simu5g-bridge/bridge.go +23 −3 Changes for go-apps/meep-simu5g-bridge/bridge.go: 23 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -67,8 +67,8 @@ func NewBridgeInstance(cfg *bridge.IntegrationConfig) (*BridgeInstance, error) { _ = tun.Close() return nil, err } log.Info("Bridge connected to simulator host S at ", cfg.BridgeTCPAddr(), " (sandbox host B, scenario=", cfg.Deployment.ScenarioID, ")") log.Info("Bridge connected to Network simulation stack at ", cfg.BridgeTCPAddr(), " (EdgeNative-Connector, scenario=", cfg.Deployment.ScenarioID, ")") return b, nil } Loading Loading @@ -180,11 +180,17 @@ func (b *BridgeInstance) loopTunToSocket(ctx context.Context) error { } pkt := buf[:n] ueID := uint16(0) if src := ipv4Source(pkt); src != nil { src := ipv4Source(pkt) if src != nil { if idx := b.cfg.ResolveUeIndexFromIP(src); idx >= 0 { ueID = uint16(idx) } } if proto := ipv4Proto(pkt); proto == 1 { log.Info("TUN UL ICMP bytes=", n, " src=", src, " dst=", ipv4Dest(pkt), " ueId=", ueID) } else { log.Debug("TUN UL bytes=", n, " proto=", proto, " src=", src, " dst=", ipv4Dest(pkt), " ueId=", ueID) } frame := bridge.EncodeDataULFrame(ueID, pkt, 0) b.mutex.Lock() conn := b.conn Loading Loading @@ -260,3 +266,17 @@ func ipv4Source(pkt []byte) net.IP { } return net.IP(pkt[12:16]).To4() } func ipv4Dest(pkt []byte) net.IP { if len(pkt) < 20 || pkt[0]>>4 != 4 { return nil } return net.IP(pkt[16:20]).To4() } func ipv4Proto(pkt []byte) uint8 { if len(pkt) < 10 || pkt[0]>>4 != 4 { return 0 } return pkt[9] }
go-packages/meep-nw-simu-catalog/instance.go +2 −2 Changes for go-packages/meep-nw-simu-catalog/instance.go: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ import ( ) /** Default sim_time_limit sent when CreateInstanceRequest.SimTimeLimit is empty. */ const DefaultSimTimeLimit = "300s" const DefaultSimTimeLimit = "1800s" // Half an hour /** * @brief POST /v1/instances request body. Loading Loading @@ -208,7 +208,7 @@ func (c *Client) DeleteInstance(ctx context.Context, sandboxID string, retainArt path := c.cfg.NemURL + "/v1/instances/" + url.PathEscape(sandboxID) if retainArtifacts { path += "?retain_artifacts=true" path += "?retain_artifacts=false" } raw, status, err := c.doInstance(ctx, http.MethodDelete, path, nil) if err != nil { Loading
tools/simu5g/install-simu5g-routes-sandbox.sh +114 −16 Changes for tools/simu5g/install-simu5g-routes-sandbox.sh: 114 added lines, 16 removed lines. Original line number Diff line number Diff line #!/usr/bin/env bash # install-simu5g-routes-sandbox.sh — Discover UE/MEC PodIPs from a sandbox namespace # by pod name, then delegate to install-simu5g-routes.sh (unchanged). # by pod name, then delegate to install-simu5g-routes.sh (policy routes + SIMU5G iptables). # # Classification (among scenario pods): # MEC — pod name starts with MEC_NAME_PREFIX (default: mep) # UE — all other scenario pods with a PodIP # # Run apply after a user activates a network scenario (PodIPs exist). Do not run # this from the Calico dataplane switch — that happens before any sandbox exists. # # The derived selectors are informational (kubectl -l cannot express name prefixes); # this script resolves PodIPs and passes UE_CIDRS / MEC_CIDRS to the base installer. # Loading @@ -32,8 +35,8 @@ CONFIG_FILE="${CONFIG_FILE:-${SCRIPT_DIR}/example-integration-config.json}" # Host routing / TUN (same defaults as install-simu5g-routes.sh) TUN_DEV="${TUN_DEV:-simu5g-br0}" TUN_ADDR="${TUN_ADDR:-169.254.250.1/32}" CNI_DEV="${CNI_DEV:-weave}" POD_CIDR="${POD_CIDR:-10.32.0.0/12}" CNI_DEV="${CNI_DEV:-}" POD_CIDR="${POD_CIDR:-}" MGMT_DEV="${MGMT_DEV:-ens160}" UPLINK_ONLY="${UPLINK_ONLY:-0}" STATE_DIR="${STATE_DIR:-/var/lib/simu5g-routes}" Loading @@ -43,6 +46,10 @@ UE_POD_SELECTOR="" MEC_POD_SELECTOR="" UE_CIDRS="" MEC_CIDRS="" mec_names=() ue_names=() mec_ips=() ue_ips=() log() { printf '[%s] %s\n' "$SCRIPT_NAME" "$*"; } die() { log "ERROR: $*"; exit 1; } Loading @@ -51,6 +58,21 @@ require_root() { [[ "${EUID:-$(id -u)}" -eq 0 ]] || die "run as root (sudo $SCRIPT_NAME $*)" } # sudo resets HOME to /root, so kubectl would miss the operator's cluster. # Prefer SUDO_USER's kubeconfig unless KUBECONFIG was set explicitly. resolve_kube_identity() { local sudo_home if [[ "${EUID:-$(id -u)}" -eq 0 && -n "${SUDO_USER:-}" && "$SUDO_USER" != "root" ]]; then sudo_home="$(getent passwd "$SUDO_USER" | cut -d: -f6)" if [[ -z "${KUBECONFIG:-}" && -n "$sudo_home" && -f "${sudo_home}/.kube/config" ]]; then export KUBECONFIG="${sudo_home}/.kube/config" log "sudo: using ${SUDO_USER} kubeconfig ${KUBECONFIG}" fi fi command -v "$KUBECTL" >/dev/null 2>&1 || die "kubectl not found (PATH=$PATH)" log "kubectl=$(command -v "$KUBECTL") KUBECONFIG=${KUBECONFIG:-<default $HOME/.kube/config>} context=$("$KUBECTL" config current-context 2>/dev/null || echo '<none>')" } # Create and bring up the bridge TUN (mirrors install-simu5g-routes.sh setup_tun). setup_tun() { if ! ip link show "$TUN_DEV" >/dev/null 2>&1; then Loading Loading @@ -84,15 +106,16 @@ Options (environment or flags): -n, --namespace NS Sandbox namespace (default: ${SANDBOX_NS}) --scenario-selector S kubectl -l filter before name split (default: ${SCENARIO_SELECTOR}) --mec-prefix P MEC pod name prefix (default: ${MEC_NAME_PREFIX}) --config-file PATH Passed to install-simu5g-routes.sh (default: example-integration-config.json) --config-file PATH Passed to install-simu5g-routes.sh; also rewrites sandboxIpCidr from live PodIPs TUN / host routing (passed through to ${INSTALLER##*/}): TUN_DEV=$TUN_DEV TUN_ADDR=$TUN_ADDR CNI_DEV=$CNI_DEV Examples: $SCRIPT_NAME discover -n sbxvipkywt sudo $SCRIPT_NAME setup-tun sudo $SCRIPT_NAME apply -n sbxvipkywt $SCRIPT_NAME discover -n sbx4lesbpo --config-file ${SCRIPT_DIR}/monaco-harbor-integration-config.json sudo $SCRIPT_NAME apply -n sbx4lesbpo --config-file ${SCRIPT_DIR}/monaco-harbor-integration-config.json # apply: TUN + ip rule table 100 + SIMU5G-FORWARD/STEER iptables for live PodIPs # If sudo still sees 0 pods: sudo KUBECONFIG=\$HOME/.kube/config $SCRIPT_NAME apply ... sudo $SCRIPT_NAME status sudo $SCRIPT_NAME delete-tun sudo $SCRIPT_NAME rollback Loading @@ -103,6 +126,7 @@ EOF parse_args() { ACTION="" CONFIG_FILE_EXPLICIT=0 while [[ $# -gt 0 ]]; do case "$1" in discover|setup-tun|apply|status|rollback|delete-tun) Loading @@ -124,6 +148,7 @@ parse_args() { ;; --config-file) CONFIG_FILE="${2:?config path required}" CONFIG_FILE_EXPLICIT=1 shift 2 ;; -h|--help|help) Loading Loading @@ -155,9 +180,15 @@ pods_to_cidr_csv() { # List scenario pods: "name<TAB>ip" per line (portable jsonpath — no ?() filter). list_scenario_pods_with_selector() { local selector=$1 local out out="$("$KUBECTL" -n "$SANDBOX_NS" get pods -l "$selector" \ -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}' 2>/dev/null)" || return 1 local out err err="$(mktemp)" if ! out="$("$KUBECTL" -n "$SANDBOX_NS" get pods -l "$selector" \ -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}' 2>"$err")"; then log "WARN: kubectl get pods -l ${selector} failed: $(tr '\n' ' ' <"$err")" rm -f "$err" return 1 fi rm -f "$err" while IFS=$'\t' read -r name ip; do [[ -n "$name" && -n "$ip" ]] || continue printf '%s\t%s\n' "$name" "$ip" Loading @@ -172,24 +203,85 @@ list_scenario_pods() { tmp="$(mktemp)" list_scenario_pods_with_selector "$SCENARIO_SELECTOR" >"$tmp" || true rows=$(grep -c . "$tmp" 2>/dev/null || echo 0) rows=$(wc -l <"$tmp" | tr -d ' ') if [[ "$rows" -eq 0 ]]; then if [[ "${rows:-0}" -eq 0 ]]; then local fallback="meepSandbox=${SANDBOX_NS}" log "WARN: no pods for -l ${SCENARIO_SELECTOR}; trying fallback -l ${fallback}" list_scenario_pods_with_selector "$fallback" >"$tmp" || true rows=$(grep -c . "$tmp" 2>/dev/null || echo 0) rows=$(wc -l <"$tmp" | tr -d ' ') fi cat "$tmp" rm -f "$tmp" } # Rewrite ueMappings/mecEndpoints sandboxIpCidr in --config-file from live pod names. write_config_cidrs() { [[ "${CONFIG_FILE_EXPLICIT:-0}" == 1 ]] || return 0 [[ -f "$CONFIG_FILE" ]] || die "--config-file not found: $CONFIG_FILE" command -v python3 >/dev/null 2>&1 || die "python3 required to rewrite $CONFIG_FILE" local pairs tmp pairs="$(mktemp)" tmp="$(mktemp)" local i for i in "${!mec_names[@]}"; do printf '%s %s\n' "${mec_names[$i]}" "${mec_ips[$i]}" >>"$pairs" done for i in "${!ue_names[@]}"; do printf '%s %s\n' "${ue_names[$i]}" "${ue_ips[$i]}" >>"$pairs" done python3 - "$CONFIG_FILE" "$pairs" "$tmp" <<'PY' import json, pathlib, sys cfg_path, pairs_path, out_path = sys.argv[1], sys.argv[2], sys.argv[3] cfg = json.loads(pathlib.Path(cfg_path).read_text()) pods = [] for line in pathlib.Path(pairs_path).read_text().splitlines(): name, ip = line.split() pods.append((name, ip)) def match_ue(ueid, name): return name == ueid or name.startswith(ueid + "-") for mapping in cfg.get("ueMappings", []): ueid = mapping.get("ueId") or "" hits = [ip for name, ip in pods if match_ue(ueid, name)] if len(hits) == 1: mapping["sandboxIpCidr"] = hits[0] + "/32" elif len(hits) > 1: print(f"WARN: multiple pods for ueId={ueid}: {hits}", file=sys.stderr) else: print(f"WARN: no pod for ueId={ueid}", file=sys.stderr) mec_pods = [(n, ip) for n, ip in pods if n.startswith("mep")] for i, ep in enumerate(cfg.get("mecEndpoints", [])): eid = ep.get("endpointId") or "" hits = [ip for n, ip in mec_pods if n.startswith(eid)] if not hits and i < len(mec_pods): hits = [mec_pods[i][1]] if hits: ep["sandboxIpCidr"] = hits[0] + "/32" else: print(f"WARN: no MEC pod for endpointId={eid}", file=sys.stderr) pathlib.Path(out_path).write_text(json.dumps(cfg, indent=2) + "\n") PY mv "$tmp" "$CONFIG_FILE" chmod 644 "$CONFIG_FILE" 2>/dev/null || true if [[ -n "${SUDO_USER:-}" && "$SUDO_USER" != "root" ]]; then chown "${SUDO_USER}:" "$CONFIG_FILE" 2>/dev/null || true fi rm -f "$pairs" log "updated sandboxIpCidr in $CONFIG_FILE from live PodIPs" } discover_pod_groups() { command -v "$KUBECTL" >/dev/null 2>&1 || die "kubectl not found" local mec_names=() ue_names=() local mec_ips=() ue_ips=() mec_names=() ue_names=() mec_ips=() ue_ips=() while IFS=$'\t' read -r name ip; do [[ -n "$name" && -n "$ip" ]] || continue Loading Loading @@ -218,6 +310,9 @@ discover_pod_groups() { printf '%s\n' "MEC_CIDRS=${MEC_CIDRS:-<none>}" printf '%s\n' "UE_CIDRS=${UE_CIDRS:-<none>}" printf '%s\n' "TUN_DEV=${TUN_DEV} TUN_ADDR=${TUN_ADDR} (use setup-tun or apply to create)" if ip link show bpfin.cali >/dev/null 2>&1; then printf '%s\n' "CNI=Calico (per-pod cali* veths) — do not pass CNI_DEV=cali...; apply auto-detects" fi printf '\n%s\n' "TUN interface:" show_tun_status printf '\n%s\n' "MEC pods (${#mec_names[@]}):" Loading @@ -241,6 +336,7 @@ discover_pod_groups() { [[ -n "$MEC_CIDRS" ]] || die "no MEC pods (name prefix '${MEC_NAME_PREFIX}') in namespace ${SANDBOX_NS}" [[ -n "$UE_CIDRS" ]] || die "no UE pods (non-${MEC_NAME_PREFIX} scenario pods) in namespace ${SANDBOX_NS}" write_config_cidrs } run_installer() { Loading Loading @@ -276,6 +372,7 @@ cmd_delete_tun() { main() { parse_args "$@" resolve_kube_identity case "$ACTION" in discover) Loading @@ -289,7 +386,8 @@ main() { ;; apply) require_root apply discover_pod_groups >/dev/null # Do not redirect discover: errors (no pods) must be visible. TUN is created only after pods exist. discover_pod_groups log "MEC_POD_SELECTOR=${MEC_POD_SELECTOR}" log "UE_POD_SELECTOR=${UE_POD_SELECTOR}" log "MEC_CIDRS=${MEC_CIDRS}" Loading
tools/simu5g/install-simu5g-routes.sh 0 → 100755 +646 −0 File added.Preview size limit exceeded, changes collapsed. Show changes
tools/simu5g/monaco-harbor-integration-config.json +42 −10 Changes for tools/simu5g/monaco-harbor-integration-config.json: 42 added lines, 10 removed lines. Original line number Diff line number Diff line Loading @@ -29,19 +29,51 @@ "meAppInst": "monaco-harbor" }, "ueMappings": [ {"ueId": "ue-car-0", "sandboxIpCidr": "10.0.0.1/32", "simu5gModulePath": "MonacoHarbor.ue_car[0]"}, {"ueId": "ue-car-1", "sandboxIpCidr": "10.0.0.2/32", "simu5gModulePath": "MonacoHarbor.ue_car[1]"}, {"ueId": "ue-car-2", "sandboxIpCidr": "10.0.0.3/32", "simu5gModulePath": "MonacoHarbor.ue_car[2]"}, {"ueId": "ue-car-3", "sandboxIpCidr": "10.0.0.4/32", "simu5gModulePath": "MonacoHarbor.ue_car[3]"}, {"ueId": "ue-ped-0", "sandboxIpCidr": "10.0.0.11/32", "simu5gModulePath": "MonacoHarbor.ue_ped[0]"}, {"ueId": "ue-ped-1", "sandboxIpCidr": "10.0.0.12/32", "simu5gModulePath": "MonacoHarbor.ue_ped[1]"}, {"ueId": "ue-ped-2", "sandboxIpCidr": "10.0.0.13/32", "simu5gModulePath": "MonacoHarbor.ue_ped[2]"}, {"ueId": "ue-ped-3", "sandboxIpCidr": "10.0.0.14/32", "simu5gModulePath": "MonacoHarbor.ue_ped[3]"} { "ueId": "ue-car-0", "sandboxIpCidr": "192.168.108.147/32", "simu5gModulePath": "MonacoHarbor.ue_car[0]" }, { "ueId": "ue-car-1", "sandboxIpCidr": "192.168.108.185/32", "simu5gModulePath": "MonacoHarbor.ue_car[1]" }, { "ueId": "ue-car-2", "sandboxIpCidr": "192.168.108.180/32", "simu5gModulePath": "MonacoHarbor.ue_car[2]" }, { "ueId": "ue-car-3", "sandboxIpCidr": "192.168.108.150/32", "simu5gModulePath": "MonacoHarbor.ue_car[3]" }, { "ueId": "ue-ped-0", "sandboxIpCidr": "192.168.108.130/32", "simu5gModulePath": "MonacoHarbor.ue_ped[0]" }, { "ueId": "ue-ped-1", "sandboxIpCidr": "192.168.108.136/32", "simu5gModulePath": "MonacoHarbor.ue_ped[1]" }, { "ueId": "ue-ped-2", "sandboxIpCidr": "192.168.108.179/32", "simu5gModulePath": "MonacoHarbor.ue_ped[2]" }, { "ueId": "ue-ped-3", "sandboxIpCidr": "192.168.108.135/32", "simu5gModulePath": "MonacoHarbor.ue_ped[3]" } ], "mecEndpoints": [ { "endpointId": "mec1", "sandboxIpCidr": "10.20.0.0/24", "endpointId": "mep1", "sandboxIpCidr": "192.168.108.134/32", "simu5gModulePath": "router" } ], Loading