Bug 29235

Summary: VLAN support for SMC EtherPower II (tx)
Product: Base System Reporter: peter.jeremy <peter.jeremy>
Component: kernAssignee: semenu <semenu>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 5.0-CURRENT   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description peter.jeremy 2001-07-25 22:40:27 UTC
	The attached patch adds 802.1Q VLAN support for the SMC
	EtherPower III (SMC9432TX) NIC - tx(4).  I have not tested
	the module version, but building it into the kernel works
	well.

How-To-Repeat: 	Apply patch, attach tx NIC to VLAN trunk, configure and play.
Comment 1 Yar Tikhiy freebsd_committer freebsd_triage 2001-07-26 13:17:57 UTC
Responsible Changed
From-To: freebsd-bugs->semenu

Over to the driver's maintainer.
Comment 2 semenu freebsd_committer freebsd_triage 2001-07-26 21:06:45 UTC
I haven't ever seen vlan. Quick look at /sys/pci/if_ti.c (seems the only 
driver supporting vlan) gives it needs more workaround... I also can't 
understand how will it receive more then ETHER_MAX_FRAME_LEN, when this 
is maximum frame len allowed
for ethrenet.

Could you explain what is vlan and how to configure/test it?
Comment 3 Yar Tikhiy freebsd_committer freebsd_triage 2001-07-27 10:45:15 UTC
Hi there,

VLAN stands for Virtual Local Area Network. Its idea is rather
simple. In a switched network, if the switches are smart enough
and support the VLAN feature, you can assign a "colour" to each
switch port (actually, it's an integer number that you assign, but
the original terminology talks of colours). The consequence of the
assignment is that only ports of the same colour can exchange
traffic. All your supernetwork breaks down into separate virtual
networks (VLANs) spread over all your switches.

The standard marketroid grounds for the whole VLAN technique is
that you no longer need separate switches for divisions of a company
if they need separate networks.

In such a case, you would need a router port *and* switch port
_per_each_VLAN_ to route packets between the VLANs. Fortunately,
there are a few protocols of tagging ethernet frames with their
VLAN IDs. At first, the protocols were used between switches
themselves because traffic of different VLANs shouldn't have "mixed"
in inter-switch links. Then someone connected such an inter-switch
port (usually called "trunk port") to a router ethernet port and
thus got a numer of logical interfaces on a single physical one,
each connected to one of the VLANs. They wrote the router VLAN
driver software first, of course.

The most popular VLAN standard nowadays is IEEE 802.1Q. According
to it, frame's ethernet protocol type is changed to a new value
defined by the standard, and a small, 32-bit header is inserted
between the ethernet header and payload. It consists of a 16-bit
VLAN tag and an original ethernet protocol type.

There are few ethernet cards around that support VLANs in
firmware, and FreeBSD doesn't need such a card to run VLANs
due to the software emulation code in the vlan(4) driver.
The only Good Thing a NIC driver can do for vlan(4) is being
able to cope with oversized frames, so a user wouldn't need to
lower the MTU of vlan(4) interfaces by 4.

As for the tx(4) driver, it just needs to indicate its capability
to handle frames longer than 1518 bytes by setting the `if_hdrlen'
field.  It's what Jeremy's patch about. It seems that Jeremy knows
what he's doing.

-- 
Yar
Comment 4 peter.jeremy 2001-07-29 21:53:39 UTC
On 2001-Jul-27 13:45:15 +0400, Yar Tikhiy <yar@FreeBSD.org> wrote:
>The most popular VLAN standard nowadays is IEEE 802.1Q. According
>to it, frame's ethernet protocol type is changed to a new value
>defined by the standard, and a small, 32-bit header is inserted
>between the ethernet header and payload. It consists of a 16-bit
>VLAN tag and an original ethernet protocol type.

Diagramatically:

A normal ethernet frame looks like:

+--------+--------+-----------+--------+--------+
| DstMAC | SrcMAC | EtherType |  Data  | CRC-32 |
+--------+--------+-----------+--------+--------+
    6        6          2      46..1500     4     bytes

IEEE 802.1Q defines an ethertype 0x8100 to indicate an VLAN frame,
which looks like:

+--------+--------+-------------+--------+-----------+------+--------+
| DstMAC | SrcMAC | Type=0x8100 | VLANid | EtherType | Data | CRC-32 |
+--------+--------+-------------+--------+-----------+------+--------+
    6        6           2          2         2      46..1500     4     bytes

Where the MAC addresses, EtherType and Data fields are as per the
original frame.  The VLANid comprises a 12-bit VLAN identifier, a
3-bit priority field and a canonical format indicator bit.  (FreeBSD
ignored the priority field and canonical format indicator bit).  In
order to handle the 4 added bytes, the maximum ethernet frame size is
increased from 1518 to 1522 bytes - supporting this extended frame is
device dependent.  Some devices (eg tl(4)) handle it automatically,
some (like tx(4)) need to be told to receive longer frames, some
devices (eg i82559) have `VLAN enable' bits and others (older fxp(4)
and de(4)) use assorted subterfuges to get the NIC to receive longer
frames.

`Tagging' a standard frame is just a matter of pre-pending a new
ethertype and length field to the frame before passing it to the
NIC - see /sys/net/if_vlan.c:vlan_start().  On reception, a tagged
frame can be detected as part of the normal EtherType processing
(see /sys/net/if_ethersubr.c:ether_demux()) and the passed to the
VLAN code for handling (/sys/net/if_vlan.c:vlan_input()).  Once the
Correct VLAN is identified, the 802.1Q tag can be stripped off and
the frame returned to the normal ethernet input handling.

The 802.1Q standard can be obtained from
http://standards.ieee.org/catalog/IEEE802.1.html (costs money), but
a search engine will turn up plenty of explanations - the first I
came across was http://www.techfest.com/networking/lan/ethernet2.htm

Peter
Comment 5 semenu freebsd_committer freebsd_triage 2001-07-30 20:37:51 UTC
Thanks for explanations. Sorry for taking so long.

The datasheet says EPIC chip might receive/transmit up to 64k frames. (It
usually have 4k RX and 1.5k TX buffers, so overflows and underruns could
happen). So there shouldn't be any voilation in making it receive 1522
bytes. Moreover, if the patch works.

The patch seems generally OK, except for the following lines:

+#if NBPF > 0
 #include <net/bpf.h>
+#endif

Added lines seems to be obsolete now.

I'm also thinking of replacing 

                desc->buflength = ETHER_MAX_FRAME_LEN;
with
		desc->buflength = sc->ifp->if_mtu + sc->ifp->if_hdrlen;

Instead of ifdefing something.

If you're agree, I'll commit this as soon as you say.
Comment 6 peter.jeremy 2001-07-30 22:27:58 UTC
On 2001-Jul-31 01:37:51 +0600, "Semen A. Ustimenko" <semenu@FreeBSD.org> wrote:
>Thanks for explanations. Sorry for taking so long.

There's no hurry.  Yar's vlan(4) page prodded me to submit code that
I initially wrote more than a year ago.

>The patch seems generally OK, except for the following lines:
>
>+#if NBPF > 0
> #include <net/bpf.h>
>+#endif
>
>Added lines seems to be obsolete now.

Agreed.  I'm not sure why I added them at the time now.

>I'm also thinking of replacing 
>
>                desc->buflength = ETHER_MAX_FRAME_LEN;
>with
>		desc->buflength = sc->ifp->if_mtu + sc->ifp->if_hdrlen;
>
>Instead of ifdefing something.

I'm less certain about this.  I understand the rationale but if you're
going to base the Rx ring sizes on the current MTU, then logically you
need to re-configure the rings if the MTU changes.

An MTU change (eg "ifconfig tx0 mtu 1234") is reported to the driver
via SIOCSIFMTU.  The tx driver just passes this onto ether_ioctl() -
this change implies that the code in epic_ifioctl() should call
epic_init_rings() or epic_init() (at least if the MTU changed).
Something like the following (untested and whitespace mangled):

--- if_tx.c     Tue Jul  3 01:17:59 2001
+++ /tmp/if_tx.c        Tue Jul 31 07:06:35 2001
@@ -655,8 +655,16 @@ epic_ifioctl(ifp, command, data)
 #if defined(__FreeBSD__)
        case SIOCSIFADDR:
        case SIOCGIFADDR:
-       case SIOCSIFMTU:
                error = ether_ioctl(ifp, command, data);
+               break;
+       case SIOCSIFMTU:
+                if (ifr->ifr_mtu > ETHERMTU) {
+                        error = EINVAL;
+                } else if (ifp->if_mtu != ifr->ifr_mtu) {
+                        ifp->if_mtu = ifr->ifr_mtu;
+                        epic_stop(sc);
+                        epic_init(sc);
+                }
                break;
 #else /* __OpenBSD__ */
        case SIOCSIFADDR: {

You could optionally delete the comparison against ETHERMTU - which
would allow people to run oversize ethernet frames if they wanted
(this is allowed in de(4) if BIG_PACKET is defined).

I gather you don't have access to any 802.1Q trunks to test VLAN
support.  I'll see if I can find the time to update and test this
change sometime this week (I need to catch up on -CURRENT mail and do
an installworld first).

Peter
Comment 7 semenu freebsd_committer freebsd_triage 2001-07-31 00:04:11 UTC
I'm totally agreed with you about ring's reconfiguration and possible
packet oversize. This may be done easily. I vote for that to be done.

On Tue, 31 Jul 2001, Peter Jeremy wrote:

> [skiped]
>
> I gather you don't have access to any 802.1Q trunks to test VLAN
> support.  I'll see if I can find the time to update and test this
> change sometime this week (I need to catch up on -CURRENT mail and do
> an installworld first).
> 
You're right. All i have - two FreeBSD machines with tx and one with
fxp. I didn't manage to make fxp work with vlan's mtu 1500, so i'll try to
test them between two tx cards. (But is surely works with mtu < 1496)

Bye!
Comment 8 semenu freebsd_committer freebsd_triage 2001-08-21 18:53:06 UTC
State Changed
From-To: open->closed

Problem was fixed, to say VLAN support was added.