// addNATFlow sets up a NAT flow // natT must be "Src" or "Dst" func (svcOp *proxyOper) addNATFlow(this, next *ofctrl.Table, p *PortSpec, ipSa, ipDa, ipNew *net.IP, natT string) { // Check if we already installed this flow key := "" if natT == "Dst" { key = getNATKey(ipSa.String(), natT, p) } else { key = getNATKey(ipDa.String(), natT, p) } f, found := svcOp.natFlows[key] if found && f != nil { log.Infof("Flow already exists for %v", key) return } match := ofctrl.FlowMatch{ Priority: FLOW_MATCH_PRIORITY, Ethertype: 0x0800, IpSa: ipSa, IpDa: ipDa, IpProto: getIPProto(p.Protocol), } if p.Protocol == "TCP" { if natT == spDNAT { match.TcpDstPort = p.SvcPort } else { match.TcpSrcPort = p.ProvPort } } else { if natT == spDNAT { match.UdpDstPort = p.SvcPort } else { match.UdpSrcPort = p.ProvPort } } natFlow, err := this.NewFlow(match) if err != nil { log.Errorf("Proxy addNATFlow failed") return } l4field := p.Protocol + natT // evaluates to TCP[Src,Dst] or UDP[Src,Dst] // add actions to update ipda and dest port natFlow.SetIPField(*ipNew, natT) if natT == spDNAT { natFlow.SetL4Field(p.ProvPort, l4field) } else { natFlow.SetL4Field(p.SvcPort, l4field) } natFlow.Next(next) svcOp.natFlows[key] = natFlow log.Infof("Added NAT %s to %s", key, ipNew.String()) }
// createPortVlanFlow creates port vlan flow based on endpoint metadata func createPortVlanFlow(agent *OfnetAgent, vlanTable, nextTable *ofctrl.Table, endpoint *OfnetEndpoint) (*ofctrl.Flow, error) { // Install a flow entry for vlan mapping portVlanFlow, err := vlanTable.NewFlow(ofctrl.FlowMatch{ Priority: FLOW_FLOOD_PRIORITY, InputPort: endpoint.PortNo, }) if err != nil { log.Errorf("Error creating portvlan entry. Err: %v", err) return nil, err } //set vrf id as METADATA vrfid := agent.getvrfId(endpoint.Vrf) metadata, metadataMask := Vrfmetadata(*vrfid) // set source EPG id if required if endpoint.EndpointGroup != 0 { srcMetadata, srcMetadataMask := SrcGroupMetadata(endpoint.EndpointGroup) metadata = metadata | srcMetadata metadataMask = metadataMask | srcMetadataMask } // set vlan if required if agent.dpName == "vxlan" { portVlanFlow.SetVlan(endpoint.Vlan) } // set metedata portVlanFlow.SetMetadata(metadata, metadataMask) // Point it to next table err = portVlanFlow.Next(nextTable) if err != nil { log.Errorf("Error installing portvlan entry. Err: %v", err) return nil, err } return portVlanFlow, nil }
// createDscpFlow creates DSCP v4/v6 flows func createDscpFlow(agent *OfnetAgent, vlanTable, nextTable *ofctrl.Table, endpoint *OfnetEndpoint) (*ofctrl.Flow, *ofctrl.Flow, error) { // if endpoint has no DSCP value, we are done.. if endpoint.Dscp == 0 { return nil, nil, nil } // Install a flow entry for DSCP v4 dscpV4Flow, err := vlanTable.NewFlow(ofctrl.FlowMatch{ Priority: FLOW_MATCH_PRIORITY, InputPort: endpoint.PortNo, Ethertype: 0x0800, }) if err != nil { log.Errorf("Error creating DSCP v4 entry. Err: %v", err) return nil, nil, err } // Install a flow entry for DSCP v6 dscpV6Flow, err := vlanTable.NewFlow(ofctrl.FlowMatch{ Priority: FLOW_MATCH_PRIORITY, InputPort: endpoint.PortNo, Ethertype: 0x86DD, }) if err != nil { log.Errorf("Error creating DSCP v6 entry. Err: %v", err) return nil, nil, err } //set vrf id as METADATA vrfid := agent.getvrfId(endpoint.Vrf) metadata, metadataMask := Vrfmetadata(*vrfid) // set source EPG id if required if endpoint.EndpointGroup != 0 { srcMetadata, srcMetadataMask := SrcGroupMetadata(endpoint.EndpointGroup) metadata = metadata | srcMetadata metadataMask = metadataMask | srcMetadataMask } // set vlan if required if agent.dpName == "vxlan" { dscpV4Flow.SetVlan(endpoint.Vlan) dscpV6Flow.SetVlan(endpoint.Vlan) } // set dscp and metadata on the flow dscpV4Flow.SetDscp(uint8(endpoint.Dscp)) dscpV6Flow.SetDscp(uint8(endpoint.Dscp)) dscpV4Flow.SetMetadata(metadata, metadataMask) dscpV6Flow.SetMetadata(metadata, metadataMask) // Point it to next table err = dscpV4Flow.Next(nextTable) if err != nil { log.Errorf("Error installing dscp v4 entry. Err: %v", err) return nil, nil, err } err = dscpV6Flow.Next(nextTable) if err != nil { log.Errorf("Error installing dscp v6 entry. Err: %v", err) return nil, nil, err } return dscpV4Flow, dscpV6Flow, nil }