usnistgov / ndn-dpdk

NDN-DPDK: High-Speed Named Data Networking Forwarder
https://www.nist.gov/publications/ndn-dpdk-ndn-forwarding-100-gbps-commodity-hardware
Other
131 stars 26 forks source link

Changing Forwarding strategies #49

Closed rohansuri1996 closed 2 years ago

rohansuri1996 commented 2 years ago

Hi,

I was thinking to experiment simple changes to how 1 host receives data from another host and I read that ndndpdk uses the least roundtrip time to find the best path but suppose I have to use some other forwarding strategy for this, for a simple example if a host has more than 1 next-hops for one data object and it wants to perform a round-robin is it possible by changing the forwarding strategy?

yoursunny commented 2 years ago

The sequential.c strategy has a round-robin behavior. It will use each nexthop of a FIB entry sequentially, skipping any invalid nexthops.

You probably know that NFD has a strategy choice table, which allows you to specify the forwarding strategy of a name prefix. In NDN-DPDK, strategy choice is combined with FIB entry, so that you have to set strategy choice at the same granularity of a FIB entry. To load a strategy and set it on a FIB entry:

  1. load a strategy:

    $ ndndpdk-ctrl load-strategy --elffile /usr/local/lib/bpf/ndndpdk-strategy-sequential.o
    {"id":"HV2SCTE55KMUJDDQKDJFGKPDNAE9SDD7OK00EUO","name":"ndndpdk-strategy-sequential.o"}
  2. insert/replace a FIB entry with strategy ID:

    $ ndndpdk-ctrl insert-fib --name /A --nexthop PJ8D6P61ES7EVBTSUOOQIII6VO \
      --strategy HV2SCTE55KMUJDDQKDJFGKPDNAE9SDD7OK00EUO
    {"id":"OFFT0AF16SUFPDF3SCTA0F0"}

To see the corresponding API call, insert --cmdout between ndndpdk-ctrl and the subcommand name. You will see mutation loadStrategy has an elf: Bytes! input parameter: it is the strategy ELF object, encoded in base64.

rohansuri1996 commented 2 years ago

Hi JunXiao,

ndndpdk-ctrl load-strategy --elffile /usr/local/lib/bpf/ndndpdk-strategy-sequential.o

Can I loadstrategy via the python script or just passing

/usr/local/lib/bpf/ndndpdk-strategy-sequential.o

in the mutation?

Currently I am able to do it on the CLI

yoursunny commented 2 years ago

Use --cmdout to see the API call, and translate to Python or other scripts yourself. This is already answered at the end of the previous comment.

rohansuri1996 commented 2 years ago

Yes I understood that but the problem was even after changing the strategy it was just sending the packets on one of the nexthops.

This is how I am loading the strategy

def loadStrategy(self):
        info('Loading strategy......')

        strategy = self.graphQLClient.fetch("""
                mutation loadStrategy($name: String!, $elf: Bytes!) {
                    loadStrategy(name: $name, elf: $elf) {
                            id
                            name
                    }
                } 

                """, {
                    "elf": "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",
                     "name": "ndndpdk-strategy-sequential.o"
                })
        strategyID= strategy['data']['loadStrategy']['id']        
        info('***strategy result %s\n' % strategy)
        info('id is %s \n ' %strategyID)

        return strategyID   

Saves the strategyID strategyID=Q.loadStrategy()

Then I am passing the strategy id into insertFIBentry

 def insertFibEntry_strategy(self, prefix, names,strategyID): # returns FIB entry ID
        ids = [ self.faces[name]['data']['createFace']['id'] for name in names]

        fib = self.graphQLClient.fetch("""
            mutation insertFibEntry($name: Name!, $nexthops: [ID!]!, $strategy: ID) {
                insertFibEntry(name: $name, nexthops: $nexthops, strategy: $strategy) {
                    id
                }
            }
        """, {
            'name': "/"+prefix ,
            'nexthops': ids ,
            'strategy' : strategyID
        })
        info('***fib result %s\n' % fib)
        info('***prefix is %s'% "'/"+prefix+"'"+ '\n')
        fib_id = fib['data']['insertFibEntry']['id']
        print(fib_id)
        return fib_id 

and calling the insertFIB function

fib_ids['V_QT'] = Q.insertFibEntry_strategy('V', ['faceQS', 'faceQT'], strategyID)

Now when i check on graphQL it shows the name and id of the strategy as seqeuntial but still sends the data using original multicast strategy

yoursunny commented 2 years ago

After re-reading the source code of sequential strategy, I think this is not what you want.

The sequential strategy uses each FIB nexthop sequentially for each retransmitted Interest on the same PIT entry. It skips any unusable nexthops (e.g. face is down).

Its granularity is per PIT entry and only acts on retransmissions. It will not use different nexthops for different Interests.

You may need to write your own strategy. See ndn-dpdk/bpf/strategy/READMD.md for how to write a strategy.

rohansuri1996 commented 2 years ago

Is there any more reading material or documentation on this part. I want to make some new strategies but I dont understand the readme. There is not much information in there.

yoursunny commented 2 years ago

You need to have a deep understanding of the forwarding plane source code. Look at how existing strategies are implemented. Then look at the data structures.

yoursunny commented 2 years ago

Commit dd3888e27dc5497cfb306cd7f56c70367690bf45 implements a simple roundrobin strategy.