-
Notifications
You must be signed in to change notification settings - Fork 31
[fw] broadcast/replicast forwarding strategy + best-route override #174
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
Merged
tianyuan129
merged 24 commits into
named-data:dv2
from
r2dev2:r2dev2/replicast-forwarding
Mar 18, 2026
Merged
Changes from 13 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
cb423ec
e2e: do not re-build ndnd binary in e2e if it is already present
r2dev2 bb8bd13
fw: add broadcast forwarding strategy
r2dev2 e2f383a
e2e: test_005 for broadcast strategy
r2dev2 890d04d
fw: fix lint
r2dev2 a81a279
e2e: move rng seed to be consistent, remove test_005 from e2e list fo…
r2dev2 687196b
fw: override forward strategy to bestroute when there is ER tag
r2dev2 80f3051
e2e: add back in test_005.scenario it works now
r2dev2 0e1bc2c
fw: do not set ER tag in broadcast
r2dev2 1fd2750
fw: implement replicast forwarding strategy
r2dev2 5dc8ee6
e2e: add tests for replicast
r2dev2 71902c4
fw: fix bestroute ER tag in case of multiple ER
r2dev2 91be66f
dv: make router use broadcast instead of multicast for advertisement …
r2dev2 3dcfc02
dv: use replicast for svs sync advertisement
r2dev2 9c4dcc5
fw: add exception in replicast for localhop/neighbors
r2dev2 284ba5e
fw: consolidate nextER and nexthops into same array for consistent so…
r2dev2 02faaf5
dv: localhop svs for routing should use broadcast strategy
r2dev2 e817034
fw: refactor strategy to take in hop/er in single array
r2dev2 797a65b
fw: add comment explaining that best-route override may be reconsider…
r2dev2 c6ffe04
alo-latest: expose the prefix to routing daemon
r2dev2 da2307a
e2e: test replicast for svs
r2dev2 652f80a
e2e: remove tests 5 and 6
r2dev2 c44e1f5
e2e: add alo-sync to makefile and ci
r2dev2 833b15a
alo-latest: fix lint
r2dev2 421209c
fw: fix bug in sorting for forwarding + copy packet when setting ER t…
r2dev2 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| import random | ||
| import os | ||
|
|
||
| from mininet.log import info | ||
| from minindn.minindn import Minindn | ||
| from minindn.apps.app_manager import AppManager | ||
|
|
||
| from fw import NDNd_FW | ||
| import dv_util | ||
|
|
||
| def scenario(ndn: Minindn, network='/minindn'): | ||
| """ | ||
| Simple file transfer scenario with NDNd forwarder. | ||
| This tests routing convergence and cat/put operations. | ||
|
|
||
| Identical to test_001 but uses broadcast forwarding strategy. | ||
| """ | ||
| info('Starting forwarder on nodes\n') | ||
| AppManager(ndn, ndn.net.hosts, NDNd_FW, network=network) | ||
|
|
||
| dv_util.setup(ndn, network=network) | ||
| dv_util.converge(ndn.net.hosts, network=network) | ||
|
|
||
| info('Testing file transfer\n') | ||
| test_file = '/tmp/test.bin' | ||
| os.system(f'dd if=/dev/urandom of={test_file} bs=64K count=1') | ||
|
|
||
| sample_size = min(8, len(ndn.net.hosts)-1) | ||
| put_nodes = random.sample(ndn.net.hosts, sample_size) | ||
| cat_nodes = random.sample(ndn.net.hosts, sample_size) | ||
| cat_requests = [(cat_node, random.choice(put_nodes)) for cat_node in cat_nodes] | ||
| put_prefixes = {f"{network}/{node.name}/test" for node in put_nodes} | ||
| control_prefixes = { | ||
| f"{network}/32=DV/32=PES/32=svs", | ||
| f"/localhop{network}/32=DV/32=ADS/32=PSV", | ||
| } | ||
|
|
||
|
|
||
| for node in put_nodes: | ||
| prefix = f"{network}/{node.name}/test" | ||
| cmd = f'ndnd put --expose "{prefix}" < {test_file} &' | ||
| info(f'{node.name} {cmd}\n') | ||
| node.cmd(cmd) | ||
|
|
||
| # New pipeline requires PET propagation before Interests can be forwarded. | ||
| expected = {node: set(put_prefixes) for node in ndn.net.hosts} | ||
| dv_util.wait_prefix_pet_ready(expected, deadline=180) | ||
|
|
||
| # Prefix traffic should remain PET-driven; app prefixes must not be injected into FIB. | ||
| for node in ndn.net.hosts: | ||
| fib = node.cmd('ndnd fw fib-list') | ||
| for prefix in put_prefixes: | ||
| if prefix in fib: | ||
| raise Exception(f'App prefix {prefix} unexpectedly present in FIB on {node.name}') | ||
| for prefix in control_prefixes: | ||
| if prefix in fib: | ||
| raise Exception(f'Control prefix {prefix} unexpectedly present in FIB on {node.name}') | ||
| if f'{network}/32=DV/32=PES/' in fib: | ||
| raise Exception(f'Router-specific PES entries unexpectedly present in FIB on {node.name}') | ||
| if f'/localhop{network}/' in fib and '/32=DV' in fib: | ||
| raise Exception(f'Router-specific localhop DV entries unexpectedly present in FIB on {node.name}') | ||
|
|
||
| # Set default forwarding strategy to broadcast for the cat interest packets | ||
| for node in ndn.net.hosts: | ||
| node.cmd("ndnd fw strategy-set prefix=/ strategy=/localhost/nfd/strategy/broadcast/v=1") | ||
|
|
||
| for node, put_node in cat_requests: | ||
| cmd = f'ndnd cat "{network}/{put_node.name}/test" > recv.test.bin 2> cat.log' | ||
| info(f'{node.name} {cmd}\n') | ||
| node.cmd(cmd) | ||
| if node.cmd(f'diff {test_file} recv.test.bin').strip(): | ||
| info(node.cmd(f'cat cat.log')) | ||
| raise Exception(f'Test file contents do not match on {node.name}') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| import random | ||
| import os | ||
|
|
||
| from mininet.log import info | ||
| from minindn.minindn import Minindn | ||
| from minindn.apps.app_manager import AppManager | ||
|
|
||
| from fw import NDNd_FW | ||
| import dv_util | ||
|
|
||
| def scenario(ndn: Minindn, network='/minindn'): | ||
| """ | ||
| Simple file transfer scenario with NDNd forwarder. | ||
| This tests routing convergence and cat/put operations. | ||
|
|
||
| Identical to test_001 but uses replicast forwarding strategy. | ||
| """ | ||
| info('Starting forwarder on nodes\n') | ||
| AppManager(ndn, ndn.net.hosts, NDNd_FW, network=network) | ||
|
|
||
| dv_util.setup(ndn, network=network) | ||
| dv_util.converge(ndn.net.hosts, network=network) | ||
|
|
||
| info('Testing file transfer\n') | ||
| test_file = '/tmp/test.bin' | ||
| os.system(f'dd if=/dev/urandom of={test_file} bs=64K count=1') | ||
|
|
||
| sample_size = min(8, len(ndn.net.hosts)-1) | ||
| put_nodes = random.sample(ndn.net.hosts, sample_size) | ||
| cat_nodes = random.sample(ndn.net.hosts, sample_size) | ||
| cat_requests = [(cat_node, random.choice(put_nodes)) for cat_node in cat_nodes] | ||
| put_prefixes = {f"{network}/{node.name}/test" for node in put_nodes} | ||
| control_prefixes = { | ||
| f"{network}/32=DV/32=PES/32=svs", | ||
| f"/localhop{network}/32=DV/32=ADS/32=PSV", | ||
| } | ||
|
|
||
|
|
||
| for node in put_nodes: | ||
| prefix = f"{network}/{node.name}/test" | ||
| cmd = f'ndnd put --expose "{prefix}" < {test_file} &' | ||
| info(f'{node.name} {cmd}\n') | ||
| node.cmd(cmd) | ||
|
|
||
| # New pipeline requires PET propagation before Interests can be forwarded. | ||
| expected = {node: set(put_prefixes) for node in ndn.net.hosts} | ||
| dv_util.wait_prefix_pet_ready(expected, deadline=180) | ||
|
|
||
| # Prefix traffic should remain PET-driven; app prefixes must not be injected into FIB. | ||
| for node in ndn.net.hosts: | ||
| fib = node.cmd('ndnd fw fib-list') | ||
| for prefix in put_prefixes: | ||
| if prefix in fib: | ||
| raise Exception(f'App prefix {prefix} unexpectedly present in FIB on {node.name}') | ||
| for prefix in control_prefixes: | ||
| if prefix in fib: | ||
| raise Exception(f'Control prefix {prefix} unexpectedly present in FIB on {node.name}') | ||
| if f'{network}/32=DV/32=PES/' in fib: | ||
| raise Exception(f'Router-specific PES entries unexpectedly present in FIB on {node.name}') | ||
| if f'/localhop{network}/' in fib and '/32=DV' in fib: | ||
| raise Exception(f'Router-specific localhop DV entries unexpectedly present in FIB on {node.name}') | ||
|
|
||
| # Set default forwarding strategy to replicast for the cat interest packets | ||
| for node in ndn.net.hosts: | ||
| node.cmd("ndnd fw strategy-set prefix=/ strategy=/localhost/nfd/strategy/replicast/v=1") | ||
|
|
||
| for node, put_node in cat_requests: | ||
| cmd = f'ndnd cat "{network}/{put_node.name}/test" > recv.test.bin 2> cat.log' | ||
| info(f'{node.name} {cmd}\n') | ||
| node.cmd(cmd) | ||
| if node.cmd(f'diff {test_file} recv.test.bin').strip(): | ||
| info(node.cmd(f'cat cat.log')) | ||
| raise Exception(f'Test file contents do not match on {node.name}') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| /** | ||
| * Broadcast forwarding strategy. | ||
| * | ||
| * Using this strategy, the interest packet will be forwarded to all nexthops. | ||
| */ | ||
|
|
||
| package fw | ||
|
|
||
| import ( | ||
| "github.com/named-data/ndnd/fw/core" | ||
| "github.com/named-data/ndnd/fw/defn" | ||
| "github.com/named-data/ndnd/fw/table" | ||
| enc "github.com/named-data/ndnd/std/encoding" | ||
| ) | ||
|
|
||
| // The strategy to forward interests to all nexthops. | ||
| type Broadcast struct { | ||
| StrategyBase | ||
| } | ||
|
|
||
| // (AI GENERATED DESCRIPTION): Registers the Broadcast strategy with version 1 in the strategy registry by appending its constructor to the init list. | ||
| func init() { | ||
| strategyInit = append(strategyInit, func() Strategy { return &Broadcast{} }) | ||
| StrategyVersions["broadcast"] = []uint64{1} | ||
| } | ||
|
|
||
| // (AI GENERATED DESCRIPTION): Initializes the *Broadcast strategy by setting up its base with the name “broadcast” and priority 1 on the provided forwarding thread. | ||
| func (s *Broadcast) Instantiate(fwThread *Thread) { | ||
| s.NewStrategyBase(fwThread, "broadcast", 1) | ||
| } | ||
|
|
||
| // (AI GENERATED DESCRIPTION): Sends a cached Data packet (retrieved from the Content Store) back to the requester via the specified PIT entry, using the requesting face and indicating the Content Store as the data source. | ||
| func (s *Broadcast) AfterContentStoreHit( | ||
| packet *defn.Pkt, | ||
| pitEntry table.PitEntry, | ||
| inFace uint64, | ||
| ) { | ||
| core.Log.Trace(s, "AfterContentStoreHit", "name", packet.Name, "faceid", inFace) | ||
| s.SendData(packet, pitEntry, inFace, 0) // 0 indicates ContentStore is source | ||
| } | ||
|
|
||
| // (AI GENERATED DESCRIPTION): Forwards a received Data packet to every face recorded in the PIT entry, logging each forwarding step and invoking SendData for each destination. | ||
| func (s *Broadcast) AfterReceiveData( | ||
| packet *defn.Pkt, | ||
| pitEntry table.PitEntry, | ||
| inFace uint64, | ||
| ) { | ||
| core.Log.Trace(s, "AfterReceiveData", "name", packet.Name, "inrecords", len(pitEntry.InRecords())) | ||
| for faceID := range pitEntry.InRecords() { | ||
| core.Log.Trace(s, "Forwarding Data", "name", packet.Name, "faceid", faceID) | ||
| s.SendData(packet, pitEntry, faceID, inFace) | ||
| } | ||
| } | ||
|
|
||
| // Forwards an incoming Interest to all next-hops | ||
| func (s *Broadcast) AfterReceiveInterest( | ||
| packet *defn.Pkt, | ||
| pitEntry table.PitEntry, | ||
| inFace uint64, | ||
| nexthops []*table.FibNextHopEntry, | ||
| nextER []enc.Name, | ||
| ) { | ||
| if len(nexthops) == 0 { | ||
| core.Log.Debug(s, "No nexthop found - DROP", "name", packet.Name) | ||
| return | ||
| } | ||
|
|
||
| successfulForward := false | ||
|
|
||
| for _, nh := range nexthops { | ||
| if sent := s.SendInterest(packet, pitEntry, nh.Nexthop, inFace); sent { | ||
| core.Log.Trace(s, "Forwarded Interest", "name", packet.Name, "faceid", nh.Nexthop) | ||
| successfulForward = true | ||
| } else { | ||
| core.Log.Trace(s, "Error forwarding interest", "name", packet.Name, "faceid", nh.Nexthop) | ||
| } | ||
| } | ||
|
|
||
| if !successfulForward { | ||
| core.Log.Debug(s, "No usable nexthop for Interest - DROP", "name", packet.Name) | ||
| } | ||
| } | ||
tianyuan129 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // (AI GENERATED DESCRIPTION): No‑op hook invoked before satisfying an Interest in the Broadcast strategy – it performs no action. | ||
| func (s *Broadcast) BeforeSatisfyInterest(pitEntry table.PitEntry, inFace uint64) { | ||
| // This does nothing in Broadcast | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.