Skip to content

Commit 3648410

Browse files
committed
ipv6
1 parent 815fcbf commit 3648410

File tree

5 files changed

+433
-10
lines changed

5 files changed

+433
-10
lines changed

roles/devscripts/tasks/130_prep_host.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
- bootstrap
4141
ansible.builtin.import_tasks: 135_patch_src.yml
4242

43+
- name: Patch dev-scripts IPv6 VIPs DNS lookup.
44+
tags:
45+
- bootstrap
46+
ansible.builtin.import_tasks: 135a_patch_ipv6_vips.yml
47+
4348
- name: Copy token and pull secret to repo.
4449
tags:
4550
- bootstrap
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
# Copyright Red Hat, Inc.
3+
# All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations
15+
# under the License.
16+
17+
# Fix dev-scripts bug where INGRESS_VIPS uses IPv4 DNS lookup even when IPv6 is configured
18+
# This patches the set_api_and_ingress_vip function in network.sh to use AAAA records for ingress
19+
# when IP_STACK is v6 or v6v4 (IPv6-only or IPv6-primary dual-stack deployments)
20+
- name: Fix INGRESS_VIPS IPv6 DNS lookup in dev-scripts
21+
when:
22+
- "'manage_br_bridge' in cifmw_devscripts_config"
23+
- cifmw_devscripts_config['manage_br_bridge'] == 'n'
24+
- cifmw_devscripts_config.get('ip_stack', 'v4') == 'v6' or
25+
cifmw_devscripts_config.get('external_subnet_v6') is defined
26+
ansible.builtin.replace:
27+
path: "{{ cifmw_devscripts_repo_dir }}/network.sh"
28+
regexp: '^(\s+)INGRESS_VIPS=\$\(dig \+noall \+answer "test\.apps\.\$\{CLUSTER_DOMAIN\}" \| awk ''\{print \$NF\}''\)$'
29+
replace: |2
30+
if [[ "${IP_STACK}" == "v6" || "${IP_STACK}" == "v6v4" ]]; then
31+
INGRESS_VIPS=$(dig -t AAAA +noall +answer "test.apps.${CLUSTER_DOMAIN}" | awk '{print $NF}')
32+
else
33+
INGRESS_VIPS=$(dig +noall +answer "test.apps.${CLUSTER_DOMAIN}" | awk '{print $NF}')
34+
fi
35+
owner: "{{ cifmw_devscripts_user }}"
36+
group: "{{ cifmw_devscripts_user }}"
37+
mode: "0644"

roles/libvirt_manager/tasks/generate_networking_data.yml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,12 @@
182182
networks:
183183
{{ _lnet_data.name | replace('cifmw_', '') }}:
184184
{% if _lnet_data.ranges[0].start_v4 is defined and _lnet_data.ranges[0].start_v4 %}
185-
{% set net_4 = _lnet_data.ranges[0].start_v4 | ansible.utils.ipsubnet(_lnet_data.ranges[0].prefix_length_v4) %}
186-
network-v4: {{ net_4}}
185+
{%- set net_4 = _lnet_data.ranges[0].start_v4 | ansible.utils.ipsubnet(_lnet_data.ranges[0].prefix_length_v4) %}
186+
network-v4: '{{ net_4 }}'
187187
{% endif %}
188188
{% if _lnet_data.ranges[0].start_v6 is defined and _lnet_data.ranges[0].start_v6 %}
189-
{% set net_6 = _lnet_data.ranges[0].start_v6 | ansible.utils.ipsubnet(_lnet_data.ranges[0].prefix_length_v6) %}
190-
network-v6: {{ net_6 }}
189+
{%- set net_6 = _lnet_data.ranges[0].start_v6 | ansible.utils.ipsubnet(_lnet_data.ranges[0].prefix_length_v6) %}
190+
network-v6: '{{ net_6 }}'
191191
{% endif %}
192192
group-templates:
193193
{% for group in _cifmw_libvirt_manager_layout.vms.keys() if group != 'controller' and
@@ -202,12 +202,12 @@
202202
{% if cifmw_networking_definition['group-templates'][_gr ~ 's']['network-template'] is undefined %}
203203
{% if net_4 is defined %}
204204
range-v4:
205-
start: {{ net_4 | ansible.utils.nthhost(ns.ip_start | int ) }}
205+
start: '{{ net_4 | ansible.utils.nthhost(ns.ip_start | int ) }}'
206206
length: {{ _cifmw_libvirt_manager_layout.vms[group].amount | default(1) }}
207207
{% endif %}
208208
{% if net_6 is defined %}
209209
range-v6:
210-
start: {{ net_6 | ansible.utils.nthhost(ns.ip_start | int) }}
210+
start: '{{ net_6 | ansible.utils.nthhost(ns.ip_start | int) }}'
211211
length: {{ _cifmw_libvirt_manager_layout.vms[group].amount | default(1) }}
212212
{% endif %}
213213
{% set ns.ip_start = ns.ip_start|int + (_cifmw_libvirt_manager_layout.vms[group].amount | default(1) | int ) + 1 %}
@@ -220,12 +220,12 @@
220220
{{ cifmw_libvirt_manager_pub_net }}:
221221
{% if net_4 is defined and cifmw_networking_definition['group-templates']['baremetals']['network-template'] is undefined %}
222222
range-v4:
223-
start: {{ net_4 | ansible.utils.nthhost(ns.ip_start) }}
223+
start: '{{ net_4 | ansible.utils.nthhost(ns.ip_start) }}'
224224
length: {{ cifmw_baremetal_hosts | length }}
225225
{% endif %}
226226
{% if net_6 is defined and cifmw_networking_definition['group-templates']['baremetals']['network-template'] is undefined %}
227227
range-v6:
228-
start: {{ net_6 | ansible.utils.nthhost(ns.ip_start) }}
228+
start: '{{ net_6 | ansible.utils.nthhost(ns.ip_start) }}'
229229
length: {{ cifmw_baremetal_hosts | length }}
230230
{% endif %}
231231
{% endif %}
@@ -235,10 +235,10 @@
235235
networks:
236236
{{ _lnet_data.name | replace('cifmw_', '') }}:
237237
{% if net_4 is defined %}
238-
ip-v4: "{{ net_4 | ansible.utils.nthhost(9) }}"
238+
ip-v4: '{{ net_4 | ansible.utils.nthhost(9) }}'
239239
{% endif %}
240240
{% if net_6 is defined %}
241-
ip-v6: "{{ net_6 | ansible.utils.nthhost(9) }}"
241+
ip-v6: '{{ net_6 | ansible.utils.nthhost(9) }}'
242242
{% endif %}
243243
{% endif %}
244244
block:
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
# dt-nfv-ovs-dpdk-sriov-2nodesets-ipv6.yml
2+
3+
## Overview
4+
5+
This reproducer is the **IPv6 variant** of `dt-nfv-ovs-dpdk-sriov-2nodesets.yml`. It configures an NFV deployment with OVS-DPDK and SR-IOV support using **IPv6 as the primary IP version** across all OpenStack networks, while maintaining dual-stack configuration on hypervisor bridges for compatibility.
6+
7+
## Key Features
8+
9+
- **IPv6 Primary**: All OpenStack networks use IPv6 addressing
10+
- **Dual-Stack ctlplane**: Both IPv4 and IPv6 IPAM for ctlplane network
11+
- **2 NodeSets**: Supports deployments with two different EDPM nodesets (different hardware)
12+
- **OVS-DPDK**: High-performance DPDK-accelerated networking
13+
- **SR-IOV**: Direct hardware access for VMs
14+
- **OpenShift IPv6**: OCP configured with IPv6 networking
15+
16+
## Network Configuration
17+
18+
### IPv6 Network Ranges
19+
20+
| Network | IPv6 Range | VLAN | Purpose |
21+
|--------------|-------------------------|------|---------|
22+
| ctlplane | 2620:cf:cf:aaaa::/64 | - | Control plane (dual-stack) |
23+
| internalapi | 2620:cf:cf:bbbb::/64 | 20 | Internal API |
24+
| storage | 2620:cf:cf:cccc::/64 | 21 | Storage network |
25+
| tenant | 2620:cf:cf:eeee::/64 | 22 | Tenant/overlay network |
26+
| storagemgmt | 2620:cf:cf:dddd::/64 | 23 | Storage management |
27+
| external | 2620:cf:cf:cf02::/64 | - | External network |
28+
29+
### OpenShift IPv6 Networks
30+
31+
| Network | IPv6 Range | Purpose |
32+
|------------------|--------------------------|---------|
33+
| provisioning | fd00:1101::/64 | Provisioning network |
34+
| external_subnet | 2620:cf:cf:cf02::/64 | External access |
35+
| service_subnet | 2620:cf:cf:cf03::/112 | OCP services |
36+
| cluster_subnet | fd01::/48 | OCP pod network |
37+
38+
## Key Differences from IPv4 Version
39+
40+
### Added Configuration
41+
42+
1. **Primary IP Version**
43+
```yaml
44+
cifmw_ci_gen_kustomize_values_primary_ip_version: 6
45+
```
46+
47+
2. **IPv6 Networking Definition**
48+
- All networks configured with IPv6 ranges
49+
- VLANs preserved from original (20-23)
50+
- MTU settings maintained
51+
52+
3. **OpenShift IPv6 Configuration**
53+
```yaml
54+
cifmw_devscripts_config_overrides:
55+
ip_stack: "v6"
56+
provisioning_network: "fd00:1101::/64"
57+
external_subnet_v6: "2620:cf:cf:cf02::/64"
58+
service_subnet_v6: "2620:cf:cf:cf03::/112"
59+
cluster_subnet_v6: "fd01::/48"
60+
```
61+
62+
4. **Dual-Stack ctlplane IPAM**
63+
```yaml
64+
ipam:
65+
type: whereabouts
66+
ipRanges:
67+
- range: "192.168.122.0/24" # IPv4 (compatibility)
68+
- range: "2620:cf:cf:aaaa::/64" # IPv6 (primary)
69+
```
70+
71+
### Unchanged Configuration
72+
73+
- VM definitions (controller, OCP nodes)
74+
- Libvirt network topology
75+
- BMH configuration
76+
- LVMS setup
77+
- EDPM image configuration
78+
79+
## Usage
80+
81+
### In Zuul Jobs
82+
83+
This reproducer is used by the IPv6 variant of NFV jobs:
84+
85+
```yaml
86+
- job:
87+
name: uni08theta-rhel9-rhoso18.0-nfv-ovs-dpdk-sriov-ipv6-trunk-patches-2nodesets
88+
vars:
89+
variable_files:
90+
- "{{ ci_framework_src }}/scenarios/reproducers/dt-nfv-ovs-dpdk-sriov-2nodesets-ipv6.yml"
91+
- ... (other variable files)
92+
```
93+
94+
### Manual Deployment
95+
96+
```bash
97+
# Set up your environment
98+
cd ~/ci-framework
99+
100+
# Create your custom variables file
101+
cat > my-ipv6-vars.yml <<EOF
102+
cifmw_devscripts_ci_token: <your-token>
103+
cifmw_devscripts_pull_secret: <your-pull-secret>
104+
hypervisor: <your-hypervisor-fqdn>
105+
EOF
106+
107+
# Deploy using this reproducer
108+
ansible-playbook deploy-edpm.yml \
109+
-e @scenarios/reproducers/dt-nfv-ovs-dpdk-sriov-2nodesets-ipv6.yml \
110+
-e @my-ipv6-vars.yml
111+
```
112+
113+
## Infrastructure Requirements
114+
115+
### Switch Configuration
116+
117+
The physical switch must support IPv6 on all VLANs:
118+
119+
```
120+
# Enable IPv6 globally
121+
ipv6 unicast-routing
122+
123+
# Configure VLAN IPv6 gateways
124+
interface Vlan20 # internalapi
125+
ipv6 address 2620:cf:cf:bbbb::1/64
126+
ipv6 nd managed-config-flag
127+
ipv6 nd prefix 2620:cf:cf:bbbb::/64
128+
129+
interface Vlan21 # storage
130+
ipv6 address 2620:cf:cf:cccc::1/64
131+
ipv6 nd managed-config-flag
132+
ipv6 nd prefix 2620:cf:cf:cccc::/64
133+
134+
interface Vlan22 # tenant
135+
ipv6 address 2620:cf:cf:eeee::1/64
136+
ipv6 nd managed-config-flag
137+
ipv6 nd prefix 2620:cf:cf:eeee::/64
138+
139+
interface Vlan23 # storagemgmt
140+
ipv6 address 2620:cf:cf:dddd::1/64
141+
ipv6 nd managed-config-flag
142+
ipv6 nd prefix 2620:cf:cf:dddd::/64
143+
144+
# Enable MLD snooping (IPv6 multicast)
145+
ipv6 mld snooping
146+
```
147+
148+
### Hypervisor Requirements
149+
150+
- **IPv6 enabled**: `sysctl net.ipv6.conf.all.disable_ipv6=0`
151+
- **IPv6 forwarding**: `sysctl net.ipv6.conf.all.forwarding=1`
152+
- **Bridges with IPv6**: All bridges (ocpbm, ocppr, osp_external, osp_trunk) must have IPv6 addresses
153+
- **Router Advertisements**: Enable RA if using SLAAC
154+
155+
### DNS Requirements
156+
157+
- DNS server with IPv6 support (AAAA records)
158+
- Reverse DNS for IPv6 (ip6.arpa zones)
159+
- DNS reachable at 2620:cf:cf:aaaa::1
160+
161+
## Topology
162+
163+
```
164+
┌─────────────────┐
165+
│ Hypervisor │
166+
│ (dual-stack) │
167+
└────────┬────────┘
168+
169+
┌────────────────────┼────────────────────┐
170+
│ │ │
171+
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
172+
│ OCP │ │ OCP │ │ OCP │
173+
│ Master │ │ Master │ │ Master │
174+
│ #1 │ │ #2 │ │ #3 │
175+
└─────────┘ └─────────┘ └─────────┘
176+
│ │ │
177+
└────────────────────┼────────────────────┘
178+
179+
┌────────▼────────┐
180+
│ controller-0 │
181+
│ (IPv6: aaaa::9) │
182+
└────────┬────────┘
183+
184+
┌────────────────────┼────────────────────┐
185+
│ │ │
186+
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
187+
│ Compute │ │ Compute │ │ Compute │
188+
│ Node │ │ Node │ │ Node │
189+
│ (Set 1) │ │ (Set 2) │ │ (Set 2) │
190+
└─────────┘ └─────────┘ └─────────┘
191+
OVS-DPDK OVS-DPDK OVS-DPDK
192+
SR-IOV SR-IOV SR-IOV
193+
```
194+
195+
## Verification
196+
197+
After deployment, verify IPv6 configuration:
198+
199+
```bash
200+
# On hypervisor - check IPv6 addresses
201+
ip -6 addr show osp_trunk
202+
# Should show: 2620:cf:cf:aaaa::1/64 (if configured by nmstate)
203+
204+
# Test connectivity to controller-0
205+
ping6 2620:cf:cf:aaaa::9
206+
207+
# On compute nodes - check IPv6 configuration
208+
ssh heat-admin@<compute-node>
209+
ip -6 addr show
210+
# Should show IPv6 addresses on bond interfaces
211+
212+
# Verify OpenStack endpoints use IPv6
213+
openstack endpoint list
214+
# Should show IPv6 addresses like [2620:cf:cf:aaaa::X]
215+
```
216+
217+
## Troubleshooting
218+
219+
### Common Issues
220+
221+
**Issue**: Computes can't reach control plane
222+
- **Check**: DHCPv6 or SLAAC working on ctlplane
223+
- **Verify**: `tcpdump -i osp_trunk -n icmp6`
224+
225+
**Issue**: Services not listening on IPv6
226+
- **Check**: `cifmw_ci_gen_kustomize_values_primary_ip_version: 6` is set
227+
- **Verify**: `ss -tlnp6` on controller
228+
229+
**Issue**: DNS resolution fails
230+
- **Check**: AAAA records exist for all services
231+
- **Verify**: `dig AAAA keystone.openstack.svc`
232+
233+
**Issue**: VLANs not working
234+
- **Check**: Switch has IPv6 enabled on VLANs 20-23
235+
- **Verify**: MLD snooping enabled
236+
237+
## Related Files
238+
239+
- **Original IPv4 reproducer**: `dt-nfv-ovs-dpdk-sriov-2nodesets.yml`
240+
- **Job definition**: `zuul.d/ci-framework-rhoso-18-rhel9-trunk-nfv-jobs.yaml`
241+
- **IPv6 UNI scenario example**: `scenarios/uni/uni04delta-ipv6/`
242+
243+
## References
244+
245+
- [IPv6 Networking in OpenStack](https://docs.openstack.org/neutron/latest/admin/config-ipv6.html)
246+
- [OVS-DPDK Documentation](https://docs.openvswitch.org/en/latest/topics/dpdk/)
247+
- [SR-IOV Configuration](https://docs.openstack.org/neutron/latest/admin/config-sriov.html)
248+
- CI Framework IPv6 examples
249+
250+
## Author
251+
252+
Generated for NFV IPv6 testing scenarios.
253+
254+
## Version History
255+
256+
- **1.0** (2025-01-06): Initial IPv6 variant created based on dt-nfv-ovs-dpdk-sriov-2nodesets.yml

0 commit comments

Comments
 (0)