click icon indicating copy to clipboard operation
click copied to clipboard

EtherSwitch configuration

Open p4pe opened this issue 4 years ago • 15 comments

Hello, I'm using EtherSwitch element in order to implement a simple switch (at first) with only one input and one output port. The click configuration is this:

from_port0::FromDevice(enp6s0f1)
to_port0::ToDevice(enp6s0f0)
in_supp, out_supp :: Suppressor;
switch::EtherSwitch()
q0 :: Queue -> to_port0;

from_port0->[0] in_supp [0] -> [0] switch [0] -> [0] out_supp [0] ->q0;

But when I'm trying to start the router, I can't and took this error:

switch.click:4: ‘switch :: EtherSwitch’ input 1 unused switch.click:4: ‘switch :: EtherSwitch’ output 1 unused

Where is my misconfiguration?

p4pe avatar Feb 12 '21 13:02 p4pe

your config says that a packet received on port 0 is sent out port 0. A switch prevents this.

from_eth0 -> [0]switch[1] -> to_eth1; from_eth1 -> [1]switch[0] -> to_eth0;

ahenning avatar Feb 13 '21 00:02 ahenning

Yes I know that a switch prevents this. It was a misunderstanding from me and I thought that the output port 0 is not the same port with the input port 0. I believe that were different ports.

p4pe avatar Feb 13 '21 09:02 p4pe

You have to build at least 2 ports to your switch, or it can't "switch" :p You have this kind of requirements in the documentation at https://github.com/kohler/click/wiki/EtherSwitch.

from_port0::FromDevice(enp6s0f0)
from_port1::FromDevice(enp6s0f1)
to_port0::ToDevice(enp6s0f0)
to_port1::ToDevice(enp6s0f1)
in_supp0, out_supp0 :: Suppressor;
in_supp1, out_supp1 :: Suppressor;
switch::EtherSwitch()
q0 :: Queue -> to_port0;
q1 :: Queue -> to_port1;

from_port0->in_supp0  -> [0] switch [0] ->  out_supp0  ->q0;
from_port1->in_supp1  -> [1] switch [1] ->  out_supp1  ->q1;

Note that I have from and to port0 tied to enp6sf0, else I think it's a call for problem.

tbarbette avatar Feb 13 '21 12:02 tbarbette

Yes, it was my misunderstanding, Ι don't know what I was thinking when I read the documentation. :p :P

p4pe avatar Feb 13 '21 17:02 p4pe

@tbarbette I saw again your configuration, If I am not completely wrong, we have ingress port enp6s0f0 and also egress port enp6s0f0.

Is this right? or I did not understand the element?

In my scenario I want something like this: switch

I followed @ahenning example. So I create a tap interface on the Switch for the incoming traffic from the vnf

 Idle -> tap :: KernelTap(1.1.0.1/24, DEVNAME vEth1);
switch::EtherSwitch()
***The right dashed line***
FromDevice(enp6s0f2)-> [0]switch[1]->Queue->ToDevice(enp6s0f3)
FromDevice(enp6s0f3)-> [1]switch[0] -> Queue -> ToDevice(enp6s0f2)
***The left dashed line***
FromDevice(vEth1)->[2]switch[3]->Queue->ToDevice(enp6s0f1) 
FromDevice(enp6s0f1)->[3]switch[2]->Queue->ToDevice(vEth1)

The VNF configuration is simple forwarder for testing:

FromDevice(enp6s0f2)->Queue->ToDevice(vEth1)

Obviously this configuration did not work and Im trying to figure out, where is my misunderstanding

p4pe avatar Feb 15 '21 13:02 p4pe

All ports have 2 sides, rx and tx. FromDevice is rx and ToDevice is tx for a real device, a real NIC.

KernelTap includes both at once for a virtual Tap. On the left of kernel tap you handle the tx and on the right the rx. There should be no Idle().

tbarbette avatar Feb 15 '21 13:02 tbarbette

Thanks for the clarification. This is my only mistake, Ι'm impressed :P ?

p4pe avatar Feb 15 '21 14:02 p4pe

@p4pe when a packet is received on a port on the switch, the switch uses the destination mac address to decide which port to switch the packet to (if the MAC is known). In your config, the packets would not take the VNF path by it self. Connecting devices to ports does not tell the switch how to switch the packets. I am assuming this is what you want to engineer with the config, i.e to redirect traffic to the VNF. If not please let me know.

If yes, and you always want the traffic to be sent to the VNF, and it will only be in the direction as per the diagram, then you don't need the complexity of the EtherSwitch. You can simply pump the packet to the KernelTap and assuming the VNF returns the packets, take the packets from KernelTap and send it out the interface you want. In that scenario the switch is not needed. from_eth0 -> [0]tap[0] -> to_eth1

Of course the L2 headers will need to be set, but that is the path to match the diagram. If the diagram is accurate, I would recommend to remove the switch.

The second scenario is that maybe some packets need to be sent to the VNF and some packets will be sent straight through the switch. This is more complex. In this scenario the switch makes sense, but how will switch know where to send the packets to? The L2 headers need to be set to determine where the packets will be switched to.

Here is another example config with a switch and KernelTap from_eth0 -> [0]switch[0] -> to_eth0; from_eth1 -> [1]switch[1] -> to_eth1; tap[0] -> [2]switch[2] -> [0]tap;

So if you want to use the switch to redirect packets to the VNF you need to do that redirect on the L2 header. In other words, lets say your KernelTap MAC address is 01:01:01:01:01:01 then before the packets are sent to the switch, the L2 header info needs to be changed so that the destination of the packets are 01:01:01:01:01. The destination in L2 header tells the switch which port the packets will be sent out. Assuming you want to redirect the traffic to the VNF, in the above config that would be port 2.

If bidirectional traffic is needed, then the EtherSwitch will make sense. Again either the traffic needs to be redirected with EtherEncap or the L2 headers needs to be set at the Source and Sink so that the L2 info tells the switch to send the packets to the tap port.

ahenning avatar Feb 15 '21 14:02 ahenning

Thank you for the answer @ahenning , yes I want the traffic to be redirected to the VNF, and then to a second VNF before goes to the sink.

I already did your first suggestion, but I was asked to do the second one with the EtherSwitch acting as an virtual switch(I was also tried a scenario with OVS and docker, but this killed the throughput). I do not need bidirectional traffic(yet), I want just to steer the traffic as I show in the figure.

Something that I forgot to say(and write in the config) is that all interfaces are on promisc mode.

p4pe avatar Feb 15 '21 15:02 p4pe

Start with no VF, then one VF, then two :p Also if you're not handling backward traffic, then the EtherSwitch will probably not be able to learn MACs, so the switch won't work? So you should maybe hard-wire your configuration (you use no switching element, just Click edges): from_eth0->tap0; tap0->tap1; tap1->to_eth0;

tbarbette avatar Feb 15 '21 15:02 tbarbette

The no VF scenario is working :P I already did this with the hard-wired approach.. (but my supervisor wants the switch...)

p4pe avatar Feb 15 '21 15:02 p4pe

Following your advice @tbarbette (I convinced my supervisor :P) not to use the etherswitch. So I have the following setup

chain

For my NAT configuration:

FromDevice(enp6s0f1)
-> Strip(14)
-> CheckIPHeader()
->rw::IPRewriter(pattern 27.32.11.3 1024-65535 - - 0 1);
rw[0]->Queue->ToDevice(vEth1);
rw[1] -> Discard;

For my IPSec:

tap :: KernelTap(192.168.5.0/24, DEVNAME vEth1)
-> c::Counter
-> Strip(14)
-> CheckIPHeader()
-> ipsec_rt::RadixIPsecLookup( 10.10.1.1/32 0,
27.32.11.3/32 10.10.2.1 1 111 1111111111111111 1111111111111111 1 0 ,
0.0.0.0/0 2
);
ipsec_rt[0]
// Receive
-> Discard;
ipsec_rt[1]
-> IPsecESPEncap()
-> IPsecAuthHMACSHA1(0)
-> IPsecAES(1)
-> UDPIPEncap(10.10.1.1 , 4500 , 192.168.2.7 , 4500)
-> EtherEncap(0x800,3c:fd:fe:05:7a:80, 3c:fd:fe:04:a4:42)
-> Queue
-> c1::Counter
-> out::ToDevice(enp6s0f1);
ipsec_rt[2]
// Default
-> Discard;
Script(wait 1, print c1.rate, loop);

But it seems that the 27.32.11.3/32 register in the radixipseclookup table does not working. Why?

p4pe avatar Feb 22 '21 10:02 p4pe

I've never used RadixIPsecLookup, and actually IPsec. You're sure you want that one and not RadixIPLookup? What are those supplementary parameters? I know the second term should be the port, then eventually the gateway. But those "1111111111" ?

BTW, you probably want "SNIFFING false" to FromDevice, as you don't want packets to continue in the IP stack.

tbarbette avatar Mar 02 '21 14:03 tbarbette

@p4pe

As Tom mentioned previously:

All ports have 2 sides, rx and tx. FromDevice is rx and ToDevice is tx for a real device, a real NIC.

Using these elements on virtual interfaces might not work so I recommend to use real NIC to save a lot of trouble.

Also I would again recommend to use Print and IPPrint elements to trace the packets. E.g. here the suspect is the Ipsec config but I doubt the packets are even passing through the KernelTap interface.

Here is an example of chaining separate click configs together: On the Linux host: ip link add veth0 type veth peer name veth1 Make sure the virtual interfaces are up

Source: FastUDPSource(1, 1000, 600, 00:0c:29:92:68:92, 192.168.32.128, 1234, 04:04:04:04:04:05, 192.168.32.132, 1234) -> Print("source") -> ToDevice(veth0);

Sink: FromDevice(veth1, PROMISC true) -> Print("fd sink") -> Discard;

ahenning avatar Mar 03 '21 10:03 ahenning

Hello, thank you very much for the directions!

p4pe avatar Mar 04 '21 13:03 p4pe