adde flowlet_switching exercise
This commit is contained in:
parent
82bde33ec7
commit
a67330c4f4
@ -1,2 +1,2 @@
|
|||||||
# tutorials
|
# tutorials
|
||||||
Holds different P4 language tutorials
|
P4 language tutorials
|
||||||
|
11
SIGCOMM_2015/flowlet_switching/commands.txt
Normal file
11
SIGCOMM_2015/flowlet_switching/commands.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
table_set_default ecmp_group _drop
|
||||||
|
table_set_default ecmp_nhop _drop
|
||||||
|
table_set_default forward _drop
|
||||||
|
table_set_default send_frame _drop
|
||||||
|
table_add ecmp_group set_ecmp_select 10.0.0.1/32 => 0 2
|
||||||
|
table_add ecmp_nhop set_nhop 0 => 10.0.1.1 1
|
||||||
|
table_add ecmp_nhop set_nhop 1 => 10.0.2.1 2
|
||||||
|
table_add forward set_dmac 10.0.1.1 => 00:04:00:00:00:00
|
||||||
|
table_add forward set_dmac 10.0.2.1 => 00:04:00:00:00:01
|
||||||
|
table_add send_frame rewrite_mac 1 => 00:aa:bb:00:00:00
|
||||||
|
table_add send_frame rewrite_mac 2 => 00:aa:bb:00:00:01
|
56
SIGCOMM_2015/flowlet_switching/p4src/includes/headers.p4
Normal file
56
SIGCOMM_2015/flowlet_switching/p4src/includes/headers.p4
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2013-present Barefoot Networks, Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
header_type ethernet_t {
|
||||||
|
fields {
|
||||||
|
dstAddr : 48;
|
||||||
|
srcAddr : 48;
|
||||||
|
etherType : 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header_type ipv4_t {
|
||||||
|
fields {
|
||||||
|
version : 4;
|
||||||
|
ihl : 4;
|
||||||
|
diffserv : 8;
|
||||||
|
totalLen : 16;
|
||||||
|
identification : 16;
|
||||||
|
flags : 3;
|
||||||
|
fragOffset : 13;
|
||||||
|
ttl : 8;
|
||||||
|
protocol : 8;
|
||||||
|
hdrChecksum : 16;
|
||||||
|
srcAddr : 32;
|
||||||
|
dstAddr: 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header_type tcp_t {
|
||||||
|
fields {
|
||||||
|
srcPort : 16;
|
||||||
|
dstPort : 16;
|
||||||
|
seqNo : 32;
|
||||||
|
ackNo : 32;
|
||||||
|
dataOffset : 4;
|
||||||
|
res : 3;
|
||||||
|
ecn : 3;
|
||||||
|
ctrl : 6;
|
||||||
|
window : 16;
|
||||||
|
checksum : 16;
|
||||||
|
urgentPtr : 16;
|
||||||
|
}
|
||||||
|
}
|
26
SIGCOMM_2015/flowlet_switching/p4src/includes/intrinsic.p4
Normal file
26
SIGCOMM_2015/flowlet_switching/p4src/includes/intrinsic.p4
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2013-present Barefoot Networks, Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
header_type intrinsic_metadata_t {
|
||||||
|
fields {
|
||||||
|
ingress_global_timestamp : 48;
|
||||||
|
lf_field_list : 32;
|
||||||
|
mcast_grp : 16;
|
||||||
|
egress_rid : 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata intrinsic_metadata_t intrinsic_metadata;
|
77
SIGCOMM_2015/flowlet_switching/p4src/includes/parser.p4
Normal file
77
SIGCOMM_2015/flowlet_switching/p4src/includes/parser.p4
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2013-present Barefoot Networks, Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
parser start {
|
||||||
|
return parse_ethernet;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ETHERTYPE_IPV4 0x0800
|
||||||
|
|
||||||
|
header ethernet_t ethernet;
|
||||||
|
|
||||||
|
parser parse_ethernet {
|
||||||
|
extract(ethernet);
|
||||||
|
return select(latest.etherType) {
|
||||||
|
ETHERTYPE_IPV4 : parse_ipv4;
|
||||||
|
default: ingress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header ipv4_t ipv4;
|
||||||
|
|
||||||
|
field_list ipv4_checksum_list {
|
||||||
|
ipv4.version;
|
||||||
|
ipv4.ihl;
|
||||||
|
ipv4.diffserv;
|
||||||
|
ipv4.totalLen;
|
||||||
|
ipv4.identification;
|
||||||
|
ipv4.flags;
|
||||||
|
ipv4.fragOffset;
|
||||||
|
ipv4.ttl;
|
||||||
|
ipv4.protocol;
|
||||||
|
ipv4.srcAddr;
|
||||||
|
ipv4.dstAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_list_calculation ipv4_checksum {
|
||||||
|
input {
|
||||||
|
ipv4_checksum_list;
|
||||||
|
}
|
||||||
|
algorithm : csum16;
|
||||||
|
output_width : 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculated_field ipv4.hdrChecksum {
|
||||||
|
verify ipv4_checksum;
|
||||||
|
update ipv4_checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IP_PROTOCOLS_TCP 6
|
||||||
|
|
||||||
|
parser parse_ipv4 {
|
||||||
|
extract(ipv4);
|
||||||
|
return select(latest.protocol) {
|
||||||
|
IP_PROTOCOLS_TCP : parse_tcp;
|
||||||
|
default: ingress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header tcp_t tcp;
|
||||||
|
|
||||||
|
parser parse_tcp {
|
||||||
|
extract(tcp);
|
||||||
|
return ingress;
|
||||||
|
}
|
132
SIGCOMM_2015/flowlet_switching/p4src/simple_router.p4
Normal file
132
SIGCOMM_2015/flowlet_switching/p4src/simple_router.p4
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2013-present Barefoot Networks, Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "includes/headers.p4"
|
||||||
|
#include "includes/parser.p4"
|
||||||
|
#include "includes/intrinsic.p4"
|
||||||
|
|
||||||
|
header_type ingress_metadata_t {
|
||||||
|
fields {
|
||||||
|
ecmp_offset : 14; // offset into the ecmp table
|
||||||
|
|
||||||
|
nhop_ipv4 : 32;
|
||||||
|
|
||||||
|
// TODO: add your flowlet metadata here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata ingress_metadata_t ingress_metadata;
|
||||||
|
|
||||||
|
action _drop() {
|
||||||
|
drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
action set_nhop(nhop_ipv4, port) {
|
||||||
|
modify_field(ingress_metadata.nhop_ipv4, nhop_ipv4);
|
||||||
|
modify_field(standard_metadata.egress_spec, port);
|
||||||
|
add_to_field(ipv4.ttl, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ECMP_BIT_WIDTH 10
|
||||||
|
#define ECMP_GROUP_TABLE_SIZE 1024
|
||||||
|
#define ECMP_NHOP_TABLE_SIZE 16384
|
||||||
|
|
||||||
|
// TODO: add flowlet id to hash fields
|
||||||
|
|
||||||
|
field_list l3_hash_fields {
|
||||||
|
ipv4.srcAddr;
|
||||||
|
ipv4.dstAddr;
|
||||||
|
ipv4.protocol;
|
||||||
|
tcp.srcPort;
|
||||||
|
tcp.dstPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_list_calculation ecmp_hash {
|
||||||
|
input {
|
||||||
|
l3_hash_fields;
|
||||||
|
}
|
||||||
|
algorithm : crc16;
|
||||||
|
output_width : ECMP_BIT_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
action set_ecmp_select(ecmp_base, ecmp_count) {
|
||||||
|
modify_field_with_hash_based_offset(ingress_metadata.ecmp_offset, ecmp_base,
|
||||||
|
ecmp_hash, ecmp_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
table ecmp_group {
|
||||||
|
reads {
|
||||||
|
ipv4.dstAddr : lpm;
|
||||||
|
}
|
||||||
|
actions {
|
||||||
|
_drop;
|
||||||
|
set_ecmp_select;
|
||||||
|
}
|
||||||
|
size : ECMP_GROUP_TABLE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
table ecmp_nhop {
|
||||||
|
reads {
|
||||||
|
ingress_metadata.ecmp_offset : exact;
|
||||||
|
}
|
||||||
|
actions {
|
||||||
|
_drop;
|
||||||
|
set_nhop;
|
||||||
|
}
|
||||||
|
size : ECMP_NHOP_TABLE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
action set_dmac(dmac) {
|
||||||
|
modify_field(ethernet.dstAddr, dmac);
|
||||||
|
}
|
||||||
|
|
||||||
|
table forward {
|
||||||
|
reads {
|
||||||
|
ingress_metadata.nhop_ipv4 : exact;
|
||||||
|
}
|
||||||
|
actions {
|
||||||
|
set_dmac;
|
||||||
|
_drop;
|
||||||
|
}
|
||||||
|
size: 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
action rewrite_mac(smac) {
|
||||||
|
modify_field(ethernet.srcAddr, smac);
|
||||||
|
}
|
||||||
|
|
||||||
|
table send_frame {
|
||||||
|
reads {
|
||||||
|
standard_metadata.egress_port: exact;
|
||||||
|
}
|
||||||
|
actions {
|
||||||
|
rewrite_mac;
|
||||||
|
_drop;
|
||||||
|
}
|
||||||
|
size: 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
control ingress {
|
||||||
|
// TODO: flowlet switching
|
||||||
|
apply(ecmp_group);
|
||||||
|
apply(ecmp_nhop);
|
||||||
|
apply(forward);
|
||||||
|
}
|
||||||
|
|
||||||
|
control egress {
|
||||||
|
apply(send_frame);
|
||||||
|
}
|
41
SIGCOMM_2015/flowlet_switching/run_demo.sh
Executable file
41
SIGCOMM_2015/flowlet_switching/run_demo.sh
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2013-present Barefoot Networks, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
|
source $THIS_DIR/../env.sh
|
||||||
|
|
||||||
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
|
SWITCH_PATH=$BMV2_PATH/targets/simple_switch/simple_switch
|
||||||
|
|
||||||
|
CLI_PATH=$BMV2_PATH/tools/runtime_CLI.py
|
||||||
|
|
||||||
|
# Probably not very elegant but it works nice here: we enable interactive mode
|
||||||
|
# to be able to use fg. We start the switch in the background, sleep for 2
|
||||||
|
# minutes to give it time to start, then add the entries and put the switch
|
||||||
|
# process back in the foreground
|
||||||
|
set -m
|
||||||
|
$P4C_BM_SCRIPT p4src/simple_router.p4 --json simple_router.json
|
||||||
|
sudo echo "sudo" > /dev/null
|
||||||
|
sudo $BMV2_PATH/targets/simple_switch/simple_switch simple_router.json \
|
||||||
|
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
||||||
|
--nanolog ipc:///tmp/bm-0-log.ipc \
|
||||||
|
--pcap &
|
||||||
|
sleep 2
|
||||||
|
$CLI_PATH --json simple_router.json < commands.txt
|
||||||
|
echo "READY!!!"
|
||||||
|
fg
|
135
SIGCOMM_2015/flowlet_switching/run_test.py
Executable file
135
SIGCOMM_2015/flowlet_switching/run_test.py
Executable file
@ -0,0 +1,135 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Copyright 2013-present Barefoot Networks, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
NUM_PACKETS = 500
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
import threading
|
||||||
|
from scapy.all import sniff
|
||||||
|
from scapy.all import Ether, IP, IPv6
|
||||||
|
from scapy.all import sendp
|
||||||
|
|
||||||
|
class PacketQueue:
|
||||||
|
def __init__(self):
|
||||||
|
self.pkts = []
|
||||||
|
self.lock = threading.Lock()
|
||||||
|
self.ifaces = set()
|
||||||
|
|
||||||
|
def add_iface(self, iface):
|
||||||
|
self.ifaces.add(iface)
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
self.lock.acquire()
|
||||||
|
if not self.pkts:
|
||||||
|
self.lock.release()
|
||||||
|
return None, None
|
||||||
|
pkt = self.pkts.pop(0)
|
||||||
|
self.lock.release()
|
||||||
|
return pkt
|
||||||
|
|
||||||
|
def add(self, iface, pkt):
|
||||||
|
if iface not in self.ifaces:
|
||||||
|
return
|
||||||
|
self.lock.acquire()
|
||||||
|
self.pkts.append( (iface, pkt) )
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
|
queue = PacketQueue()
|
||||||
|
|
||||||
|
def pkt_handler(pkt, iface):
|
||||||
|
if IPv6 in pkt:
|
||||||
|
return
|
||||||
|
queue.add(iface, pkt)
|
||||||
|
|
||||||
|
class SnifferThread(threading.Thread):
|
||||||
|
def __init__(self, iface, handler = pkt_handler):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.iface = iface
|
||||||
|
self.handler = handler
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
sniff(
|
||||||
|
iface = self.iface,
|
||||||
|
prn = lambda x: self.handler(x, self.iface)
|
||||||
|
)
|
||||||
|
|
||||||
|
class PacketDelay:
|
||||||
|
def __init__(self, bsize, bdelay, imin, imax, num_pkts = 100):
|
||||||
|
self.bsize = bsize
|
||||||
|
self.bdelay = bdelay
|
||||||
|
self.imin = imin
|
||||||
|
self.imax = imax
|
||||||
|
self.num_pkts = num_pkts
|
||||||
|
self.current = 1
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
if self.num_pkts <= 0:
|
||||||
|
raise StopIteration
|
||||||
|
self.num_pkts -= 1
|
||||||
|
if self.current == self.bsize:
|
||||||
|
self.current = 1
|
||||||
|
return random.randint(self.imin, self.imax)
|
||||||
|
else:
|
||||||
|
self.current += 1
|
||||||
|
return self.bdelay
|
||||||
|
|
||||||
|
|
||||||
|
pkt = Ether()/IP(dst='10.0.0.1', ttl=64)
|
||||||
|
|
||||||
|
port_map = {
|
||||||
|
1: "veth3",
|
||||||
|
2: "veth5",
|
||||||
|
3: "veth7"
|
||||||
|
}
|
||||||
|
|
||||||
|
iface_map = {}
|
||||||
|
for p, i in port_map.items():
|
||||||
|
iface_map[i] = p
|
||||||
|
|
||||||
|
queue.add_iface("veth3")
|
||||||
|
queue.add_iface("veth5")
|
||||||
|
|
||||||
|
for p, iface in port_map.items():
|
||||||
|
t = SnifferThread(iface)
|
||||||
|
t.daemon = True
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
import socket
|
||||||
|
|
||||||
|
send_socket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW,
|
||||||
|
socket.htons(0x03))
|
||||||
|
send_socket.bind((port_map[3], 0))
|
||||||
|
|
||||||
|
delays = PacketDelay(10, 5, 25, 100, NUM_PACKETS)
|
||||||
|
ports = []
|
||||||
|
print "Sending", NUM_PACKETS, "packets ..."
|
||||||
|
for d in delays:
|
||||||
|
# sendp is too slow...
|
||||||
|
# sendp(pkt, iface=port_map[3], verbose=0)
|
||||||
|
send_socket.send(str(pkt))
|
||||||
|
time.sleep(d / 1000.)
|
||||||
|
time.sleep(1)
|
||||||
|
iface, pkt = queue.get()
|
||||||
|
while pkt:
|
||||||
|
ports.append(iface_map[iface])
|
||||||
|
iface, pkt = queue.get()
|
||||||
|
print ports
|
BIN
SIGCOMM_2015/flowlet_switching/solution.tar.gz
Normal file
BIN
SIGCOMM_2015/flowlet_switching/solution.tar.gz
Normal file
Binary file not shown.
26
SIGCOMM_2015/flowlet_switching/veth_setup.sh
Executable file
26
SIGCOMM_2015/flowlet_switching/veth_setup.sh
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
noOfVeths=18
|
||||||
|
if [ $# -eq 1 ]; then
|
||||||
|
noOfVeths=$1
|
||||||
|
fi
|
||||||
|
echo "No of Veths is $noOfVeths"
|
||||||
|
idx=0
|
||||||
|
let "vethpairs=$noOfVeths/2"
|
||||||
|
while [ $idx -lt $vethpairs ]
|
||||||
|
do
|
||||||
|
intf0="veth$(($idx*2))"
|
||||||
|
intf1="veth$(($idx*2+1))"
|
||||||
|
idx=$((idx + 1))
|
||||||
|
if ! ip link show $intf0 &> /dev/null; then
|
||||||
|
ip link add name $intf0 type veth peer name $intf1
|
||||||
|
ip link set dev $intf0 up
|
||||||
|
ip link set dev $intf1 up
|
||||||
|
TOE_OPTIONS="rx tx sg tso ufo gso gro lro rxvlan txvlan rxhash"
|
||||||
|
for TOE_OPTION in $TOE_OPTIONS; do
|
||||||
|
/sbin/ethtool --offload $intf0 "$TOE_OPTION" off
|
||||||
|
/sbin/ethtool --offload $intf1 "$TOE_OPTION" off
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
sysctl net.ipv6.conf.$intf0.disable_ipv6=1
|
||||||
|
sysctl net.ipv6.conf.$intf1.disable_ipv6=1
|
||||||
|
done
|
Loading…
x
Reference in New Issue
Block a user