During the last 2 days i have been trying to limit ingress PPPoE traffic passing through a 3750 switch. In order to be as strict as possible, i didn't want to drop any PPP/PPPoE control packets, like PPP keepalives/LCP auth or PADI/PADO/PADR/PADS, otherwise there was a high possibility that the PPPoE connections of some users would be dropped (because of missed PPP keepalives) or would not be established (because of missed PPPoE discovery packets).
The PPPoE connections start from the user's CPE and end at a 10000 router (bras). A rough network diagram is the following:
CPE --- DSLAM --- ME-3400 ----------|
CPE --- DSLAM --- ME-3400 ------- 3750 --- 7600 --- 10000 --- internet
CPE --- DSLAM --- ME-3400 ----------|
Double-tagging happens between the 3750 and the 10000 router (each ME-3400 represents a S-VLAN).
Since normal LAN cards (67xx) on the 7600 cannot do egress shaping/policing on L2 ports and PRE-2 on 10000 doesn't support hierarchical ethernet QoS, i though i should try to limit the downstream traffic (from internet to CPE) on the 3750.
Here comes the fun part...
3750 doesn't support (direct) classification based on CoS.
3750(config)#class-map TEST
3750(config-cmap)#match ?
access-group Access group
input-interface Select one or more input interfaces to match
ip IP specific values
That would be the best solution, because the 10000 marks by default all the PPP/PPPoE control packet with CoS 7, so it would be very easy to distinguish them from the normal/data packets (that have CoS 0).
Then i though of using the ethertype field to differentiate the 2 PPPoE classes. PPPoE uses 2 different ethertypes, one for its discovery stage and one for its session stage.
mac access-list extended PPPoE-DISCOVERY
permit any any 0x8863 0x0
mac access-list extended PPPoE-SESSION
permit any any 0x8864 0x0
class-map match-any PPPoE-DATA-CLASS
match access-group name PPPoE-SESSION
class-map match-any PPPoE-CONTROL-CLASS
match access-group name PPPoE-DISCOVERY
That would also be a good solution, although i would miss the PPP control packets. But there is a major problem here. The PPPoE ethertype is hidden inside the double-tagged frame so it cannot be checked.
PPPoE : Dest-MAC | Source-MAC | Ethertype | Payload
0x8863
single-tagged PPPoE : Dest-MAC | Source-MAC | Ethertype | Tag | Ethertype | Payload
0x8100 0x8863
double-tagged PPPoE : Dest-MAC | Source-MAC | Ethertype | Tag | Ethertype | Tag | Ethertype | Payload
0x8100 0x8100 0x8863
0x8100 is the ethertype used by the 802.1q standard. Cisco uses what i would call a "hack" in order to implement 802.1q tunneling (or QinQ). It uses the same value (0x8100) for the inner and outer ethertype.
There is an option to change the outer ethertype from the 10000's side (making it -among other choices- 802.1ad compliant), but you have to change it for all the subinterfaces of a main interface and of course you cannot define it explicitly for PPPoE control packets.
10000(config-if)#dot1q tunneling ethertype ?
0x88A8 dot1q tunneling etype 0x88A8
0x9100 dot1q tunneling etype 0x9100
0x9200 dot1q tunneling etype 0x9200
So what solved my problem? The following very simple config:
mac access-list extended PPPoE-DISCOVERY
permit any any cos 7
mac access-list extended PPPoE-SESSION
permit any any cos 0
That way we can have indirect classification based on CoS.
Like we have DSCP & IP Prec match for ip access-lists, we can have a CoS match for mac access-lists. Just keep in mind that CoS (like most things) in switches is only checked by hardware. Packets forwarded or bridged by software are treated as having a CoS of 0 in ACL matches.
Here is an interesting question for all of you: How do you match IP traffic based on CoS?