Ejemplo n.º 1
0
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
}