Question regarding HostToHostIntent.builder()

86 views
Skip to first unread message

Lukas Hubschmid

unread,
Jun 22, 2015, 3:01:01 PM6/22/15
to onos-d...@onosproject.org
Hello everybody,

I am using the intentService inside my application and came accross a
few questions.
I used the ifwd-app as sample:
https://github.com/opennetworkinglab/onos-app-samples/blob/master/ifwd/src/main/java/org/onosproject/ifwd/IntentReactiveForwarding.java

In the method setUpConnectivity (at the very end of the
IntentReactiveForwarding class), a TrafficSelector
(DefaultTrafficSelect.emptySelector()) and TrafficTreatment
(DefaultTrafficTreatment.emptyTreatment()) is being created and passed
to HostToHostIntent.builder() to create the intent.

I was able to create intent without passing a selector or a treatment
object, so:
What is the idea of creating an empty TrafficSelector and an empty
TrafficTreatment?
Can I e.g. use the selector to influence the matching of the installed
flows (e.g. match no only on Layer 2 / Ethernet, but also on Layer 3 / IP)?

Many thanks in advance!

Kind regards,
Lukas

Jonathan Hart

unread,
Jun 23, 2015, 12:18:10 PM6/23/15
to Lukas Hubschmid, onos-d...@onosproject.org
Hi Lukas,

It seems it is not necessary to pass a selector or treatment to the HostToHostIntent builder because internally it creates an empty selector and treatment anyway. 

Judging by the code it looks like it is possible to add additional match conditions by supplying your own selector to the HostToHostIntent builder - the supplied selector will be augmented with the MAC addresses of the two specified hosts. One pitfall is that it looks like the same selector will be used for both directions of the path - so if you were to add a destination IP address for example, this would be matched in both directions which is probably not what you want. In this case it is probably better to use PointToPointIntents directly because they'll give you more flexibility.

Thanks,
Jono



--
You received this message because you are subscribed to the Google Groups "ONOS Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to onos-discuss...@onosproject.org.
To post to this group, send email to onos-d...@onosproject.org.
Visit this group at http://groups.google.com/a/onosproject.org/group/onos-discuss/.
To view this discussion on the web visit https://groups.google.com/a/onosproject.org/d/msgid/onos-discuss/55885B61.3060005%40pop.agri.ch.

Lukas Hubschmid

unread,
Jun 23, 2015, 2:14:56 PM6/23/15
to onos-d...@onosproject.org
Hello Jonathan,

Thank you very much for your reply!

In the meantime I stumbled accross the same points you mentioned.
In our application, we install the intent using HostToHostIntent.builder().
See code snipplet #1 afterwards.

To "solve" the problem with the same selector for the return path, I extended the compile-method of HostToHostIntentCompiler.
It swaps the necessary fields of the selector for the return path.
I guess there is a much better / nicer way to do this, but it seems to work for now ;)
See code snipplet #2 afterwards.

But regardless if I use the original code or the customized one, I get an "Failed installation" error (and afterwards a "Failed withdrawal" error) from the IntentManager (see output at the very end).
The flows seem to be correctly installed in OpenVSwitch (and is obviously not rejected by OVS), as they show up shortly before they are removed again (almost instantly):
root@pve01:~# ovs-ofctl -OOpenFlow13 dump-flows vmbr3
OFPST_FLOW reply (OF1.3) (xid=0x2):
 cookie=0x1c00009cefeb95, duration=0.001s, table=0, n_packets=0, n_bytes=0, send_flow_rem priority=123,tcp,in_port=3,dl_src=9a:4f:7f:6c:12:9d,dl_dst=ee:74:7f:4e:a8:ef,nw_src=10.0.0.10,nw_dst=10.0.0.11,tp_src=43243,tp_dst=80,tcp_flags=0x010 actions=output:2
 cookie=0x1c00009cfdff55, duration=0s, table=0, n_packets=0, n_bytes=0, send_flow_rem priority=123,tcp,in_port=2,dl_src=ee:74:7f:4e:a8:ef,dl_dst=9a:4f:7f:6c:12:9d,nw_src=10.0.0.11,nw_dst=10.0.0.10,tp_src=80,tp_dst=43243,tcp_flags=0x010 actions=output:3


Does anyone have a clue why the flows are installed but instantly withdrawn?
Is there a method which checks the successful flow / intent installation and fails because it does not understand the TCP flags or something like that?


Many thanks in advance!

Kind regards,
Lukas

Code snipplet #1 - Intent Installation (we extended OpenFlowJ and ONOS to support TCP flag matching for OVS 2.3.1):
        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchIPSrc(IpPrefix.valueOf(ipSrc, 32))
                .matchIPDst(IpPrefix.valueOf(ipDst, 32));
        selectorBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP)
                .matchTcpSrc(tcpSrc)
                .matchTcpDst(tcpDst)
                .matchTcpFlags((short) 16);
        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();

        Intent intent = HostToHostIntent.builder()
                .appId(appId)
                .key(generateKey(ethSrc, ethDst, ipSrc, ipDst, tcpSrc, tcpDst))
                .one(srcId)
                .two(dstId)
                .selector(selectorBuilder.build())
                .treatment(treatment)
                .build();
        intentService.submit(intent);


Code snipplet #2 - Swapping of selector match fields for return path
        if (intent.selector() != null) {
            TrafficSelector.Builder reversedSelectorBuilder = DefaultTrafficSelector.builder();

            // Swap values (e.g. src with dst and vice versa)
            for (Criterion crit : intent.selector().criteria()) {
                switch (crit.type()) {
                    case ETH_SRC: reversedSelectorBuilder.matchEthDst(((EthCriterion) crit).mac());
                        break;
                    case ETH_DST: reversedSelectorBuilder.matchEthSrc(((EthCriterion) crit).mac());
                        break;
                    case IPV4_SRC: reversedSelectorBuilder.matchIPDst(((IPCriterion) crit).ip());
                        break;
                    case IPV4_DST: reversedSelectorBuilder.matchIPSrc(((IPCriterion) crit).ip());
                        break;
                    case TCP_SRC: reversedSelectorBuilder.matchTcpDst((short) ((TcpPortCriterion) crit).tcpPort());
                        break;
                    case TCP_DST: reversedSelectorBuilder.matchTcpSrc((short) ((TcpPortCriterion) crit).tcpPort());
                        break;
                    case UDP_SRC: reversedSelectorBuilder.matchUdpDst((short) ((UdpPortCriterion) crit).udpPort());
                        break;
                    case UDP_DST: reversedSelectorBuilder.matchUdpSrc((short) ((UdpPortCriterion) crit).udpPort());
                        break;
                    default: reversedSelectorBuilder.add(crit);
                        break;
                }

            }
            // Create a temporary HostToHostIntent with our reversed selector
            HostToHostIntent reversedIntent = HostToHostIntent.builder()
                    .appId(intent.appId())
                    .one(intent.two())
                    .two(intent.one())
                    .selector(reversedSelectorBuilder.build())
                    .treatment(intent.treatment())
                    .constraints(intent.constraints())
                    .priority(intent.priority())
                    .build();
            // Create the first path intent with the original intent
            // Create the second path intent with the reversed intent
            return Arrays.asList(createPathIntent(pathOne, one, two, intent),
                                 createPathIntent(pathTwo, two, one, reversedIntent));
        } else {
            // Original code
            return Arrays.asList(createPathIntent(pathOne, one, two, intent),
                                 createPathIntent(pathTwo, two, one, intent));
        }


"Failed installation" error from IntentManager (a bit formatted ;) ):
2015-06-23 17:37:43,625 | WARN  | vice-installer-3 | IntentManager                    | 77 - org.onosproject.onos-core-net - 1.3.0.SNAPSHOT | Failed installation:
9A:4F:7F:6C:12:9D,
EE:74:7F:4E:A8:EF,
167772170,
167772171,
-22293,
80
HostToHostIntent{
    id=0x54,
    key=9A:4F:7F:6C:12:9D,EE:74:7F:4E:A8:EF,167772170,167772171,-22293,80,
    appId=DefaultApplicationId{
        id=30,
        name=ch.fhnw.technik.ip6.imvs28.sfw
    },
    priority=100,
    resources=[
        9A:4F:7F:6C:12:9D/-1,
        EE:74:7F:4E:A8:EF/-1],
    selector=DefaultTrafficSelector{
        criteria=[
            TCP_SRC{tcpPort=43243},
            TCP_FLAGS{bitmask=16},
            IP_PROTO{protocol=6},
            IPV4_DST{ip=10.0.0.11/32},
            ETH_TYPE{ethType=800},
            TCP_DST{tcpPort=80},
            IPV4_SRC{ip=10.0.0.10/32}
        ]
    },
    treatment=DefaultTrafficTreatment{
        immediate=[], deferred=[], transition=None, cleared=false, metadata=null
    },
    constraints=[],
    one=9A:4F:7F:6C:12:9D/-1,
    two=EE:74:7F:4E:A8:EF/-1
}
on FlowRuleOperations{
    stages=[
        [
            FlowRuleOperation{
                rule=DefaultFlowRule{
                    id=1c00009cefeb95,
                    deviceId=of:000076645f70a44a,
                    priority=123,
                    selector=[
                        TCP_SRC{tcpPort=43243},
                        TCP_FLAGS{bitmask=16},
                        IP_PROTO{protocol=6},
                        IPV4_DST{ip=10.0.0.11/32},
                        ETH_TYPE{ethType=800},
                        TCP_DST{tcpPort=80},
                        IN_PORT{port=3},
                        IPV4_SRC{ip=10.0.0.10/32},
                        ETH_SRC{mac=9A:4F:7F:6C:12:9D},
                        ETH_DST{mac=EE:74:7F:4E:A8:EF}
                    ],
                    treatment=[OUTPUT{port=2}],
                    tableId=0,
                    created=1435073850612,
                    payLoad=null
                },
                type=ADD
            },
            FlowRuleOperation{
                rule=DefaultFlowRule{
                    id=1c00009cfdff55,
                    deviceId=of:000076645f70a44a,
                    priority=123,
                    selector=[
                        TCP_FLAGS{bitmask=16},
                        TCP_SRC{tcpPort=80},
                        IP_PROTO{protocol=6},
                        IPV4_DST{ip=10.0.0.10/32},
                        TCP_DST{tcpPort=43243},
                        ETH_TYPE{ethType=800},
                        IN_PORT{port=2},
                        IPV4_SRC{ip=10.0.0.11/32},
                        ETH_SRC{mac=EE:74:7F:4E:A8:EF},
                        ETH_DST{mac=9A:4F:7F:6C:12:9D}
                    ],
                    treatment=[OUTPUT{port=3}],
                    tableId=0,
                    created=1435073850612,
                    payLoad=null
                },
                type=ADD
            }
        ]
    ]
}

Jonathan Hart

unread,
Jun 23, 2015, 5:16:44 PM6/23/15
to Lukas Hubschmid, onos-d...@onosproject.org
Yes, I think this will be because TCP_FLAGS is not yet understood by FlowModBuilder.java. FlowModBuilder is taking the flow stats replies from the switches and constructing FlowEntry objects so we can compare them against the objects in our store. If this comparison doesn't match correctly the flow will be removed because ONOS decides that it is not supposed to be on the switch. You should be able to easily add the ability to parse TCP_FLAGS in the FlowModBuilder class.

Thanks,
Jono

Lukas Hubschmid

unread,
Jun 23, 2015, 6:19:38 PM6/23/15
to Jonathan Hart, onos-d...@onosproject.org
Hello Jonathan,

Thank you for your fast response!
We have extended FlowModBuilder.java and created TcpFlagsCriterion.java etc. similiar to ICMPV4_TYPE / IcmpTypeCriterion.java (because of the short bitmask, but with 9 bits instead):
            case TCP_FLAGS:
                tcpFlagsCriterion = (TcpFlagsCriterion) c;
                mBuilder.setExact(MatchField.OVS_TCP_FLAGS,
                                  U16.of(tcpFlagsCriterion.bitmask()));
                break;

Otherwise, the flow installation would not succeed too.
Maybe I have overseen something, but I could not find any "comparing method" or equals()-method inside FlowModBuilder.java or DefaultFlowEntry.java.
Do you know by chance where the flow stat replies are being handled? Then I could try to track it down from there.

Thank you very much for your help!

Kind regards,
Lukas

Jonathan Hart

unread,
Jun 23, 2015, 6:22:26 PM6/23/15
to Lukas Hubschmid, onos-d...@onosproject.org
Sorry I meant the FlowEntryBuilder. FlowModBuilder is used on the way down, and FlowEntryBuilder is used on the way back up to construction FlowEntries like I described in the previous mail. Check the FlowEntryBuilder has been upgraded to understand TCP_FLAGS.

Lukas Hubschmid

unread,
Jun 23, 2015, 7:09:12 PM6/23/15
to Jonathan Hart, onos-d...@onosproject.org
FlowEntryBuilder is also already extended:
            case OVS_TCP_FLAGS:
                builder.matchTcpFlags((short) match.get(MatchField.OVS_TCP_FLAGS).getValue());
                break;

Also tried directly with getRaw() (returns short instead of int).
More investigation tomorrow.

Thank you!

Kind regards,
Lukas

Lukas Hubschmid

unread,
Jun 24, 2015, 8:22:04 AM6/24/15
to Jonathan Hart, onos-d...@onosproject.org
Hello Jonathan,

Finally we were able to solve this problem.
We extended the openflowj library to use 0x80005402 (class=OpenFlow basic, field=42, hasmask=false (0), length=2) for installing flows with TCP match fields in OpenVSwitch.
Interestingly, OVS accepted and understood this, even though field 42 is not contained in OFPXMC_OPENFLOW_BASIC in the OF standard until OF 1.5.0.
I took a look at the FLOW MOD and FLOW STATS messages using Wireshark and noted, that the field is listed differently in the FLOW STATS messages than in the FLOW MOD (ADD) messages:
0x00014402 (class=OFPXMC_NXM_1, field=34, hasmask=false (0), length=2)
I think, FlowEntryBuilder did not understood our TCP_FLAGS because of this difference.
I changed the openflowj library to correctly use the experimenter extension (class OFPXMC_NXM_1) and it works now.

Thank you very much for pointing me into the right direction!

Kind regards,
Lukas

henry.j...@gmail.com

unread,
Jun 15, 2018, 6:37:40 AM6/15/18
to ONOS Discuss, jo...@onlab.us
Hi  Lucas:

We face the same problem with you, could you tell us how you modify loxi to make the flow to match tcp flag

thank you

在 2015年6月24日星期三 UTC+8下午8:22:04,lousek1992写道:
Reply all
Reply to author
Forward
0 new messages