I need to emulate a network, introducing for instance random delay, and I need help to use NetEm.
The scenario consists in two Ubuntu 14.04 machines: A and B.
A and B have ip addresses 192.168.0.1 and 192.168.0.2 on eth1.
To avoid to mess with the NICs eth1, I have set virtual interfaces eth1:
sudo ifconfig eth1:1 192.168.1.x/24 up
At this point, only on B, I add the delay as follows:
sudo tc qdisc add dev eth1:1 root netem delay 50ms 10ms 25%
The problem is that this delay is experienced also on the physical NICs eth1. I mean, if I ping the addresses on eth1 (192.168.0.1 pings 192.168.0.2), the packets are delayed as if they were heading to eth1:1. Instead, I would expect delay only on eth1:1.
What happened? How can I solve this problem?
Moreover, I read that in this way, the network impairments affect only the egress traffic. How can I introduce delays both for the egress and the ingress traffic?
Related
Can someone explain me please, because I don't understand the following concept.
In tc you can add a dummy qdisc which can process a fraction of traffic by some specific rules.
For exapmle, here you create an explicit ingress qdisc for eth0.
No idea by the way what is the point of this, like ingress qdisc isn't included by default.
$TC qdisc add dev eth0 ingress handle ffff:0
Then you apply a filter which calls an action to redirect incoming traffic
with some rule (0 0) to a dummy device (ifb0).
But the filtered traffic is marked as "egress"!
Why is that so? SHouldn't this traffic also appear as ingress in ifb0?
$TC filter add dev eth0 parent ffff: protocol ip prio 10 u32 \
match u32 0 0 flowid 1:1 \
action mirred egress redirect dev ifb0
Or does ingress mean any traffic queued inside qdisk (both incoming and outgoing traffic).
So let's say the network card received some data and before starting working with it, the kernel queued it in some qdisc. That data is ingress. The moment this data is dequeued for processing by the system, it became egress?
And the vice versa, the application sends some data to some ip address, so before giving this data to network card, the kernel puts this data into appropriate qdisc. So when it happens this data becomes ingress. Then after the data was processed by an appropriate class and was dequeued to be passed to network card, this data became egress?
Or maybe it's ingress is all traffic coming from the network card to the kernel?
In this case why there is egress in
action mirred egress redirect dev ifb0
Is it because the traffic is taken from the "ingress" part of the root qdisc owned by the network card, so when the "taking for redirection" takes place this data becomes "egress"?
Why "egress"?
I don't understand(
Indeed, but consider this:
The TC qdisc direction pertains to the actual direction of traffic. Ingress means network port->interface as according to this reference:
https://tldp.org/HOWTO/Adv-Routing-HOWTO/lartc.adv-qdisc.ingress.html
The TC filter action mirror/redirect direction is relative to the interface. Ingress means mirror/redirect the packet as it comes into the filter. Egress means mirror/redirect the packet as it goes out of the filter. The difference is that other actions can potentially transform the packet on a match. So what goes into the filter might be different from what goes out of the filter. The command basically allows the user to decide if the original packet or the modified packet is to be mirrored/redirected.
Check this out: https://man7.org/linux/man-pages/man8/tc-mirred.8.html
I have an interface eth0, from which I want to mirror all incoming traffic to, say, eth1, so I use the following commands:
tc qdisc add dev eth0 handle ffff: ingress
tc filter add dev eth0 parent ffff: prio 1 u32 match u32 0 0 action mirred ingress mirror dev eth1
It works perfectly with everything except VLAN-tagged packets - they can be seen in Wireshark on eth0, but they do not appear on eth1. If I do:
vconfig add eth0 $TAG
Where $TAG is some tag from my input traffic, the corresponding packets start to appear on eth1.
But, as I have written, I want to capture all incoming traffic, and that means I want to capture all VLAN tags as well. I'm pretty sure it will work if I add all tags from 2 up to 4094, creating all those sub-interfaces, but I wonder if there is some smarter way to do so? Also, I'm concerned about performance issues, which may appear when having so much interfaces. Thanks!
After researching more I have discovered that the utility bridge, which is part of iproute2 collection, can be used to solve this issue. I have no idea why the following approach works, but you can try to do the same if you have a similar problem.
So, suppose we already have the setup I described earlier (without vconfig-adding the VLAN tags), then do:
ip link add bridge_dev type bridge
ip link set bridge_dev up
ip link set eth0 master bridge_dev
These commands create a bridge device, turn it on and set eth0 device as a slave of the bridge_dev. Right after the last command I start seeing the VLAN-tagged packets on eth1, as expected.
Note that you can also add VLAN tags to bridge devices, like:
bridge vlan add vid 2-4094 dev bridge_dev self
I expected to only see VLAN packets after that command, but apparently it's not necessary. I would welcome anyone who could explain, why this works.
I have a dual port ethernet NIC and let's say I have connected 2 ports in a loop and assigned the following IPs to the 2 ethernet interfaces:
eth2 -> 192.168.2.1
eth3 -> 192.168.3.1
I want to send traffic from 1 port to another over the physical network, e.g. ping 192.168.3.1 from 192.168.2.1. However, the TCP/IP stack in the Linux kernel recognizes that these two addresses are local and instead sends the traffic to the loopback adapter, so the traffic never hits the physical network.
The closest I have to a solution is Anastasov's send-to-self patch, which unfortunately, has been discontinued since kernel 3.6 so it won't work on Ubuntu 13.10 (kernel 3.11) for me. I've tried finding rewriting the patch for 3.11, but I can't seem to locate these in the Ubuntu distro:
include/linux/inetdevice.h
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/route.c
Documentation/networking/ip-sysctl.txt
Is there a way I can get the send-to-self patch to work, or an alternative?
You can use network namespaces for this purpose.
As ip-netns's manpage says:
A network namespace is logically another copy of the network stack,
with its own routes, firewall rules, and network devices.
Following is just a copy of this answer:
Create a network namespace and move one of interfaces into it:
ip netns add test
ip link set eth1 netns test
Start a shell in the new namespace:
ip netns exec test bash
Then proceed as if you had two machines. When finished exit the shell and delete the namespace:
ip netns del test
you can try configuring route table, by running "ip" command:
ip route add to unicast 192.168.3.1 dev eth2
ip route add to unicast 192.168.2.1 dev eth3
new route would be added into route table, and it should be able to take effect before egress routing lookup hit the host-local route between "192.168.3.1" and "192.168.2.1", therefore, the traffic should be sent through physical interface "eth2" and "eth3", instead of loopback "lo"
Never tried myself, but should work.
Am using Cent OS 6.2 (64bit), I have 4 NIC interface, in that am trying to connect two NIC with different subnet,
em1 with 10.30.2.x series
em4 with 10.30.4.x series
Also I added route with /sbin/route add -net 10.30.4.0 netmask 255.255.255.0 dev em4
When I make the network device up "ifup em4" am not able to ping both the interfaces.
There is no IPtables running and selinux also disabled.
The same setup is working in one more DELL server, in that server reverse IP and IP forwarding is not enabled, even then its working.
Reverse IP & IP Forwarding
cat /proc/sys/net/ipv4/conf/em2/rp_filter
1
cat /proc/sys/net/ipv4/ip_forward
0
Any comments would be appreciated.
Thanks in advance.
If you are sure that ip addresses are actually setted on the interfaces, everything should work out, i would suggest to check network equipment on the way.
easiest way to test this is to use tcpdump -i any icmp and see if you actually receive the packets, this will also show you if your pong is going on the wrong interface.
hope that helps
I want send out data from one NIC and received by another NIC on a CENTOS6.4( X86 frame ,3 NIC, one is onboard realtek's, the other two is intel NICs ).
First,I configured intel nic ip: (eth0) 192.168.1.1/24 and (eth1) 192.168.1.2/24 on two intel NICs.
Second, I add route by following cmds:
# route add -host 192.168.1.1 dev eth1
# route add -host 192.168.1.2 dev eth0
Third, I enabled accept_local in /etc/sysctl.conf:
net.ipv4.conf.eth0.accept_local = 1
net.ipv4.conf.eth1.accept_local = 1
And I also disabled iptables and SElinux. I reboot the system, then use a wire connect eth0 and eth1, then I test like this:
#ping 192.168.1.1 -I eth1
Message returned:
"From 192.168.1.2 icmp_seq=xx Destination Host Unreachable"
Has I missed something?
I have read this topic How can configure linux routing to send packets out one interface, over a bridge and into another interface on the same box already.
try set sysctl -w net.ipv4.conf.all.rp_filter=2
Refer https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
accept_local - BOOLEAN
Accept packets with local source addresses. In combination
with suitable routing, this can be used to direct packets
between two local interfaces over the wire and have them
accepted properly.
rp_filter must be set to a non-zero value in order for
accept_local to have an effect.
rp_filter - INTEGER
0 - No source validation.
1 - Strict mode as defined in RFC3704 Strict Reverse Path
Each incoming packet is tested against the FIB and if the interface
is not the best reverse path the packet check will fail.
By default failed packets are discarded.
2 - Loose mode as defined in RFC3704 Loose Reverse Path
Each incoming packet's source address is also tested against the FIB
and if the source address is not reachable via any interface
the packet check will fail.
Current recommended practice in RFC3704 is to enable strict mode
to prevent IP spoofing from DDos attacks. If using asymmetric routing
or other complicated routing, then loose mode is recommended.
The max value from conf/{all,interface}/rp_filter is used
when doing source validation on the {interface}.
Default value is 0. Note that some distributions enable it
in startup scripts.