func (self actionPush) Process(data *Frame) (*outputToPort, *outputToGroup, error) { var buf []gopacket.Layer found := false switch self.Type { case ofp4.OFPAT_PUSH_VLAN: for i, layer := range data.Layers() { buf = append(buf, layer) if found == false { switch layer.LayerType() { case layers.LayerTypeEthernet: eth := layer.(*layers.Ethernet) ethertype := eth.EthernetType eth.EthernetType = layers.EthernetType(self.Ethertype) dot1q := &layers.Dot1Q{Type: ethertype} if d, ok := data.layers[i+1].(*layers.Dot1Q); ok { dot1q.Priority = d.Priority dot1q.DropEligible = d.DropEligible dot1q.VLANIdentifier = d.VLANIdentifier } buf = append(buf, dot1q) found = true } } } case ofp4.OFPAT_PUSH_MPLS: for i, layer := range data.Layers() { if found == false { var ttl uint8 var base gopacket.Layer var mpls *layers.MPLS switch t := layer.(type) { case *layers.MPLS: base = data.layers[i-1] ttl = t.TTL mpls = t case *layers.IPv4: base = data.layers[i-1] ttl = t.TTL case *layers.IPv6: base = data.layers[i-1] ttl = t.HopLimit case *layers.ARP: base = data.layers[i-1] } if base != nil { if base.LayerType() == layers.LayerTypeEthernet { base.(*layers.Ethernet).EthernetType = layers.EthernetType(self.Ethertype) } else if base.LayerType() == layers.LayerTypeDot1Q { base.(*layers.Dot1Q).Type = layers.EthernetType(self.Ethertype) } else { return nil, nil, errors.New("unsupported") } if mpls != nil { buf = append(buf, &layers.MPLS{ Label: mpls.Label, TrafficClass: mpls.TrafficClass, StackBottom: false, TTL: ttl, }) } else { buf = append(buf, &layers.MPLS{ StackBottom: true, TTL: ttl, }) } found = true } } buf = append(buf, layer) } case ofp4.OFPAT_PUSH_PBB: for _, layer := range data.Layers() { buf = append(buf, layer) if found == false { switch layer.LayerType() { case layers.LayerTypeEthernet: eth := layer.(*layers.Ethernet) ethertype := eth.EthernetType eth.EthernetType = layers.EthernetType(self.Ethertype) buf = append(buf, &layers2.PBB{ DstMAC: eth.DstMAC, SrcMAC: eth.SrcMAC, Type: ethertype, }) found = true } } } default: return nil, nil, ofp4.MakeErrorMsg( ofp4.OFPET_BAD_ACTION, ofp4.OFPBAC_BAD_TYPE, ) } if found { data.layers = buf } else { return nil, nil, errors.New("push vlan failed") } return nil, nil, nil }