Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support AntreaNetworkPolicy reject action in Traceflow #2032

Merged
merged 1 commit into from
Apr 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 24 additions & 35 deletions pkg/agent/controller/traceflow/packetin.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,23 +72,34 @@ func (c *Controller) HandlePacketIn(pktIn *ofctrl.PacketIn) error {

func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Traceflow, *crdv1alpha1.NodeResult, *crdv1alpha1.Packet, error) {
matchers := pktIn.GetMatches()
var match *ofctrl.MatchField

// Get data plane tag.
// Directly read data plane tag from packet.
var err error
var tag uint8
var ctNwDst, ipDst string
if pktIn.Data.Ethertype == protocol.IPv4_MSG {
ipPacket, ok := pktIn.Data.Data.(*protocol.IPv4)
if !ok {
return nil, nil, nil, errors.New("invalid traceflow IPv4 packet")
}
tag = ipPacket.DSCP
ctNwDst, err = getCTDstValue(matchers, false)
if err != nil {
return nil, nil, nil, err
}
ipDst = ipPacket.NWDst.String()
} else if pktIn.Data.Ethertype == protocol.IPv6_MSG {
ipv6Packet, ok := pktIn.Data.Data.(*protocol.IPv6)
if !ok {
return nil, nil, nil, errors.New("invalid traceflow IPv6 packet")
}
tag = ipv6Packet.TrafficClass >> 2
ctNwDst, err = getCTDstValue(matchers, true)
if err != nil {
return nil, nil, nil, err
}
ipDst = ipv6Packet.NWDst.String()
} else {
return nil, nil, nil, fmt.Errorf("unsupported traceflow packet Ethertype: %d", pktIn.Data.Ethertype)
}
Expand Down Expand Up @@ -139,32 +150,6 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl
}

// Collect Service DNAT.
ctNwDst := ""
ipDst := ""
switch pktIn.Data.Ethertype {
case protocol.IPv4_MSG:
ipPacket, ok := pktIn.Data.Data.(*protocol.IPv4)
if !ok {
return nil, nil, nil, errors.New("invalid traceflow IPv4 packet")
}
ctNwDst, err = getCTDstValue(matchers, false)
if err != nil {
return nil, nil, nil, err
}
ipDst = ipPacket.NWDst.String()
case protocol.IPv6_MSG:
ipPacket, ok := pktIn.Data.Data.(*protocol.IPv6)
if !ok {
return nil, nil, nil, errors.New("invalid traceflow IPv6 packet")
}
ctNwDst, err = getCTDstValue(matchers, true)
if err != nil {
return nil, nil, nil, err
}
ipDst = ipPacket.NWDst.String()
default:
return nil, nil, nil, fmt.Errorf("unsupported traceflow packet ether type %d", pktIn.Data.Ethertype)
}
if isValidCtNw(ctNwDst) && ipDst != ctNwDst {
ob := &crdv1alpha1.Observation{
Component: crdv1alpha1.ComponentLB,
Expand All @@ -175,7 +160,7 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl
}

// Collect egress conjunctionID and get NetworkPolicy from cache.
if match = getMatchRegField(matchers, uint32(openflow.EgressReg)); match != nil {
if match := getMatchRegField(matchers, uint32(openflow.EgressReg)); match != nil {
egressInfo, err := getRegValue(match, nil)
if err != nil {
return nil, nil, nil, err
Expand All @@ -189,7 +174,7 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl
}

// Collect ingress conjunctionID and get NetworkPolicy from cache.
if match = getMatchRegField(matchers, uint32(openflow.IngressReg)); match != nil {
if match := getMatchRegField(matchers, uint32(openflow.IngressReg)); match != nil {
ingressInfo, err := getRegValue(match, nil)
if err != nil {
return nil, nil, nil, err
Expand All @@ -205,14 +190,18 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl
// Get drop table.
if tableID == uint8(openflow.EgressMetricTable) || tableID == uint8(openflow.IngressMetricTable) {
ob := getNetworkPolicyObservation(tableID, tableID == uint8(openflow.IngressMetricTable))
if match = getMatchRegField(matchers, uint32(openflow.CNPDenyConjIDReg)); match != nil {
if match := getMatchRegField(matchers, uint32(openflow.CNPDenyConjIDReg)); match != nil {
notAllowConjInfo, err := getRegValue(match, nil)
if err != nil {
return nil, nil, nil, err
}
npRef := c.networkPolicyQuerier.GetNetworkPolicyByRuleFlowID(notAllowConjInfo)
if npRef != nil {
ob.NetworkPolicy = npRef.ToString()
if ruleRef := c.networkPolicyQuerier.GetRuleByFlowID(notAllowConjInfo); ruleRef != nil {
if npRef := ruleRef.PolicyRef; npRef != nil {
ob.NetworkPolicy = npRef.ToString()
}
if ruleRef.Action != nil && *ruleRef.Action == crdv1alpha1.RuleActionReject {
ob.Action = crdv1alpha1.ActionRejected
}
}
}
obs = append(obs, *ob)
Expand All @@ -226,14 +215,14 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1alpha1.Tracefl
ob := new(crdv1alpha1.Observation)
tunnelDstIP := ""
isIPv6 := c.nodeConfig.NodeIPAddr.IP.To4() == nil
if match = getMatchTunnelDstField(matchers, isIPv6); match != nil {
if match := getMatchTunnelDstField(matchers, isIPv6); match != nil {
tunnelDstIP, err = getTunnelDstValue(match)
if err != nil {
return nil, nil, nil, err
}
}
var outputPort uint32
if match = getMatchRegField(matchers, uint32(openflow.PortCacheReg)); match != nil {
if match := getMatchRegField(matchers, uint32(openflow.PortCacheReg)); match != nil {
outputPort, err = getRegValue(match, nil)
if err != nil {
return nil, nil, nil, err
Expand Down
1 change: 1 addition & 0 deletions pkg/apis/crd/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const (
ActionReceived TraceflowAction = "Received"
ActionForwarded TraceflowAction = "Forwarded"
ActionDropped TraceflowAction = "Dropped"
ActionRejected TraceflowAction = "Rejected"
// ActionForwardedOutOfOverlay indicates that the packet has been forwarded out of the network
// managed by Antrea. This indicates that the Traceflow request can be considered complete.
ActionForwardedOutOfOverlay TraceflowAction = "ForwardedOutOfOverlay"
Expand Down
1 change: 1 addition & 0 deletions pkg/controller/traceflow/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ func (c *Controller) checkTraceflowStatus(tf *crdv1alpha1.Traceflow) error {
}
if ob.Action == crdv1alpha1.ActionDelivered ||
ob.Action == crdv1alpha1.ActionDropped ||
ob.Action == crdv1alpha1.ActionRejected ||
ob.Action == crdv1alpha1.ActionForwardedOutOfOverlay {
receiver = true
}
Expand Down
66 changes: 63 additions & 3 deletions test/e2e/traceflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,29 @@ func TestTraceflowIntraNodeANP(t *testing.T) {
failOnError(err, t)

node1 := nodeName(0)
node1Pods, _, node1CleanupFn := createTestBusyboxPods(t, data, 2, node1)
node1Pods, _, node1CleanupFn := createTestBusyboxPods(t, data, 3, node1)
defer node1CleanupFn()

var denyIngress *secv1alpha1.NetworkPolicy
denyIngressName := "test-anp-deny-ingress"
if denyIngress, err = data.createANPDenyIngress("antrea-e2e", node1Pods[1], denyIngressName); err != nil {
if denyIngress, err = data.createANPDenyIngress("antrea-e2e", node1Pods[1], denyIngressName, false); err != nil {
t.Fatalf("Error when creating Antrea NetworkPolicy: %v", err)
}
defer func() {
if err = data.deleteAntreaNetworkpolicy(denyIngress); err != nil {
t.Errorf("Error when deleting Antrea NetworkPolicy: %v", err)
}
}()
var rejectIngress *secv1alpha1.NetworkPolicy
rejectIngressName := "test-anp-reject-ingress"
if rejectIngress, err = data.createANPDenyIngress("antrea-e2e", node1Pods[2], rejectIngressName, true); err != nil {
t.Fatalf("Error when creating Antrea NetworkPolicy: %v", err)
}
defer func() {
if err = data.deleteAntreaNetworkpolicy(rejectIngress); err != nil {
t.Errorf("Error when deleting Antrea NetworkPolicy: %v", err)
}
}()
antreaPod, err := data.getAntreaPodOnNode(node1)
if err = data.waitForNetworkpolicyRealized(antreaPod, denyIngressName, v1beta2.AntreaNetworkPolicy); err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -146,6 +156,53 @@ func TestTraceflowIntraNodeANP(t *testing.T) {
},
},
},
{
name: "ANPRejectIngressIPv4",
ipVersion: 4,
tf: &v1alpha1.Traceflow{
ObjectMeta: metav1.ObjectMeta{
Name: randName(fmt.Sprintf("%s-%s-to-%s-%s-", testNamespace, node1Pods[0], testNamespace, node1Pods[2])),
},
Spec: v1alpha1.TraceflowSpec{
Source: v1alpha1.Source{
Namespace: testNamespace,
Pod: node1Pods[0],
},
Destination: v1alpha1.Destination{
Namespace: testNamespace,
Pod: node1Pods[2],
},
Packet: v1alpha1.Packet{
IPHeader: v1alpha1.IPHeader{
Protocol: protocolTCP,
},
TransportHeader: v1alpha1.TransportHeader{
TCP: &v1alpha1.TCPHeader{
DstPort: 80,
Flags: 2,
},
},
},
},
},
expectedPhase: v1alpha1.Succeeded,
expectedResults: []v1alpha1.NodeResult{
{
Node: node1,
Observations: []v1alpha1.Observation{
{
Component: v1alpha1.ComponentSpoofGuard,
Action: v1alpha1.ActionForwarded,
},
{
Component: v1alpha1.ComponentNetworkPolicy,
ComponentInfo: "IngressMetric",
Action: v1alpha1.ActionRejected,
},
},
},
},
},
{
name: "ANPDenyIngressIPv6",
ipVersion: 6,
Expand Down Expand Up @@ -1759,8 +1816,11 @@ func compareObservations(expected v1alpha1.NodeResult, actual v1alpha1.NodeResul
}

// createANPDenyIngress creates an Antrea NetworkPolicy that denies ingress traffic for pods of specific label.
func (data *TestData) createANPDenyIngress(key string, value string, name string) (*secv1alpha1.NetworkPolicy, error) {
func (data *TestData) createANPDenyIngress(key string, value string, name string, isReject bool) (*secv1alpha1.NetworkPolicy, error) {
dropACT := secv1alpha1.RuleActionDrop
if isReject {
dropACT = secv1alpha1.RuleActionReject
}
anp := secv1alpha1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Expand Down