Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
994a428
gitignore: ignore Python bytecode
Jafaral Aug 25, 2026
4cac0d5
gre: Set Ethernet multicast dest when forwarding overlay traffic onto…
Jafaral Aug 25, 2026
2e90e80
mgre: Inject overlay multicast once per mapped unicast peer
Jafaral Aug 25, 2026
765783f
mgre: learn unicast peers from kernel neigh via map ...,dynamic
Jafaral Aug 25, 2026
da0952d
protolib: encapsulate collect-md GRE on send
Jafaral Aug 25, 2026
92ccac3
tests: add tests for different GRE configs/modes
Jafaral Aug 21, 2026
3c52337
tests: add chained five-mode GRE/mGRE mutest with host LANs
Jafaral Aug 25, 2026
70dbe8e
mgre: inject and demux GRE-in-mcast on wildcard mGRE
Jafaral Aug 27, 2026
226b4ce
tests: add mixed unicast/mcast mGRE mutest
Jafaral Aug 27, 2026
d15aeaa
docs: document GRE map, dynamic, and overlay multicast inject
Jafaral Aug 25, 2026
26210cb
Add nrlsmf show command for runtime status queries
Jafaral Aug 28, 2026
a992ce9
docs: document nrlsmf --cli show commands
Jafaral Aug 28, 2026
8ab63a3
tests: cover cli show commands in 1-hop mutest
Jafaral Aug 28, 2026
64d0eeb
Add show tunnel and show tunnel neighbors
Jafaral Aug 28, 2026
1d183bf
docs: document show tunnel and neighbor flags
Jafaral Aug 28, 2026
a927244
tests: query nrlsmf show commands as JSON in mutests
Jafaral Aug 28, 2026
9446fac
mgre: deliver and send EM_ACK on wildcard GRE
Jafaral Aug 29, 2026
04b218f
show: add recv/sent counters and nested group details
Jafaral Aug 29, 2026
424db8d
show: add igmp groups and interface Managed flag
Jafaral Aug 29, 2026
53e8a88
elastic: seed last-hop FORWARD from IGMP/static membership
Jafaral Aug 29, 2026
57c18bf
tests: static mGRE elastic last hop with with-frr
Jafaral Aug 29, 2026
978cf7f
docs: document show groups, igmp groups, and interface Managed
Jafaral Aug 29, 2026
3d3475e
tests: add elastic overlay to mixed mGRE mutest
Jafaral Aug 30, 2026
a96f851
bump the version to 1.4
Jafaral Aug 28, 2026
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ makefiles/nrlsmf
# generated documentation site bundle
doc/site/

# python
__pycache__/
*.pyc

# object files
*.o

Expand Down
769 changes: 658 additions & 111 deletions doc/nrlsmf.html

Large diffs are not rendered by default.

Binary file modified doc/nrlsmf.pdf
Binary file not shown.
1,189 changes: 1,023 additions & 166 deletions doc/nrlsmf.xml

Large diffs are not rendered by default.

66 changes: 62 additions & 4 deletions include/mcastFib.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,39 @@ class MulticastFIB
void Update(unsigned int elapsedTime);
void Prune(unsigned int currentTime, unsigned int ageMax);

// Packet count plus a ~5s window for recent pps (ticks are microseconds).
class RateStat
{
public:
RateStat()
: total(0), window_count(0), window_start(0) {}
void Note(unsigned int tick)
{
total++;
if ((0 == window_start) || ((tick - window_start) > 5000000u))
{
window_start = tick;
window_count = 0;
}
window_count++;
}
unsigned int GetTotal() const
{return total;}
double GetPps(unsigned int now) const
{
if ((0 == window_start) || (0 == window_count))
return 0.0;
unsigned int dt = (now >= window_start) ? (now - window_start) : 0;
if (0 == dt)
return 0.0;
return (double)window_count * 1.0e6 / (double)dt;
}
private:
unsigned int total;
unsigned int window_count;
unsigned int window_start;
};

// TBD - what's the best way to sort our BucketList???
// a) time-ordered linked list like our Entry ActiveList, or
// b) indexed by interface index (using this for now)
Expand All @@ -89,6 +122,12 @@ class MulticastFIB

unsigned int GetInterfaceIndex() const
{return iface_index;}
void NoteSent(unsigned int tick)
{sent_stat.Note(tick);}
unsigned int GetSentPkts() const
{return sent_stat.GetTotal();}
double GetSentPps(unsigned int now) const
{return sent_stat.GetPps(now);}
void CopyStatus(const TokenBucket& bucket)
{
forwarding_status = bucket.forwarding_status;
Expand Down Expand Up @@ -120,6 +159,7 @@ class MulticastFIB
unsigned int token_interval; // microseconds per packet (1.0e+06 / packetsPerSecond)
unsigned int bucket_count;
unsigned int ticker_prev; // last time bucket was updated (microsecond ticks)
RateStat sent_stat;
}; // end class MulticastFIB::TokenBucket

// List of token buckets indexed by outbound iface index
Expand Down Expand Up @@ -700,6 +740,12 @@ class MulticastFIB
unsigned int Age(unsigned int currentTick);
unsigned int GetUpdateCount() const
{return update_count;}
void NoteRecv(unsigned int tick)
{recv_stat.Note(tick);}
unsigned int GetRecvPkts() const
{return recv_stat.GetTotal();}
double GetRecvPps(unsigned int now) const
{return recv_stat.GetPps(now);}
unsigned int GetUpdateInterval() const;
bool UpdatePending() const;
//unsigned int GetAge(unsigned int currentTick) const;
Expand Down Expand Up @@ -762,6 +808,7 @@ class MulticastFIB
unsigned int acking_interval_max; // in microseconds
unsigned int acking_interval_min; // in microseconds
UINT8 flow_ttl;
RateStat recv_stat;

Entry* active_prev;
Entry* active_next;
Expand Down Expand Up @@ -937,6 +984,8 @@ class MulticastFIB
{return downstream_relay_count;}

void PrintDownstreamRelayList(FILE* filePtr = NULL); // to ProtoDebug by default
DownstreamRelayList& AccessDownstreamRelayList()
{return downstream_relay_list;}

/*void SetUpstreamRelayAddress(const ProtoAddress& relayAddr, const ProtoAddress& advAddr)
{
Expand Down Expand Up @@ -1223,8 +1272,10 @@ class MulticastFIB
#ifdef ADAPTIVE_ROUTING
bool ParseFlowList( ProtoPktIP& pkt, Entry*& fibEntry, unsigned int currentTick, bool& sendAck,const ProtoAddress& srcMac);
#endif // ADAPTIVE_ROUTING
void DumpFlowList(bool brief, std::ostringstream& ss);
void DumpFlowListJson(bool brief, std::ostringstream& ss);
void DumpFlowList(bool brief, std::ostringstream& ss, bool details = false,
unsigned int currentTick = 0);
void DumpFlowListJson(bool brief, std::ostringstream& ss, bool details = false,
unsigned int currentTick = 0);

private:
EntryTable flow_table; // Table of detected flows (updated by forwarding plane)
Expand Down Expand Up @@ -1352,11 +1403,16 @@ class ElasticMulticastForwarder
{
public:
virtual bool SendFrame(unsigned int ifaceIndex, char* buffer, unsigned int length) = 0;
// Optional GRE dest (mGRE EM_ACK to one underlay peer).
virtual bool SendFrameTo(unsigned int ifaceIndex, char* buffer, unsigned int length,
const ProtoAddress& dest)
{return SendFrame(ifaceIndex, buffer, length);}
}; // end class ElasticMulticastForwarder::OutputMechanism
void SetOutputMechanism(OutputMechanism* mech)
{output_mechanism = mech;}

void DumpGroups(bool brief, bool useJson, std::ostringstream& ss);
void DumpGroups(bool brief, bool useJson, std::ostringstream& ss, bool details = false);
void DumpManagedGroups(bool useJson, std::ostringstream& ss);

protected:
// Our "ticker" is a count of microseconds that is used for our
Expand Down Expand Up @@ -1450,7 +1506,9 @@ class ElasticMulticastController
MulticastFIB::MembershipTable& AccessMembershipTable()
{return membership_table;}

void DumpGroups(bool brief, bool useJson, std::ostringstream& ss);
void DumpGroups(bool brief, bool useJson, std::ostringstream& ss, bool details = false);
void DumpMemberships(bool useJson, std::ostringstream& ss);
void DumpManagedGroups(bool useJson, std::ostringstream& ss);

// NEXT STEP - IMPLEMENT MECHANISM TO SEND ACKS to UPSTREAM FORWARDERS
// 1) When do we send an ACK?
Expand Down
Loading
Loading