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

[wip] snabb top --yang: dump RFC7223 interface stats as JSON #886

Merged
merged 21 commits into from
Jul 13, 2016

Conversation

eugeneia
Copy link
Member

@eugeneia eugeneia commented Apr 19, 2016

This picks up on #766 to provide RFC7223 interface statistics as shared memory and updates snabb top to be able to access and format the information. In brief:

  • Extends core.app to support app-local counters under counters/$app
  • Adds RFC7223-based counters to Intel10G and VhostUser apps
  • Adds snabb top --counters <app> to list app counters
  • Adds snabb top --yang to dump RFC7223 model as JSON, including three interface types: hardware (NICs), virtual (VhostUser), link (links)

Open questions / to-do:

  • shared memory hierarchy is a bit of a mess, have to think how to structure it in case we want to support other types of app-local shm besides counters
  • which counters to provide and how: right now Intel10G does not expose unicast/multicast statistics as it does not provide the required statistics registers per queue (also only packets that actually go over the wire are counted, no NIC-switched packets); RFC7223 does not define a total packets count so rxpackets/txpackets counters are useless. Right now I mostly use the existing data to fill in applicable YANG fields: See VhostUser changes for a more pro-active example.
  • JSON does not support 64bit numbers so I convert these values to strings, RFC7223 defines drop counts as 32bit so I truncate those values to the lower 32 bits. Maybe JSON is a bad encoding for this?

Cc @lukego

Appendix:

YANG/JSON output looks like this:

{
  "interface-state": [
    {
      "type": "link",
      "name": "B_NIC.tx -> B_Filter_in.rx",
      "statistics": {
        "in-octets": "0x00000000000005D2",
        "out-octets": "0x00000000000005D2",
        "discontinuity-time": "2016-04-19T15:56:31Z",
        "out-discards": 0
      }
    },
    {
      "type": "link",
      "name": "A_Virtio.tx -> A_NIC.rx",
      "statistics": {
        "in-octets": "0x00000000000005D2",
        "out-octets": "0x00000000000005D2",
        "discontinuity-time": "2016-04-19T15:56:31Z",
        "out-discards": 0
      }
    },
    {
      "type": "link",
      "name": "B_Virtio.tx -> B_Filter_out.rx",
      "statistics": {
        "in-octets": "0x00000000000002E9",
        "out-octets": "0x00000000000002E9",
        "discontinuity-time": "2016-04-19T15:56:49Z",
        "out-discards": 0
      }
    },
    {
      "type": "link",
      "name": "B_Filter_out.tx -> B_NIC.rx",
      "statistics": {
        "in-octets": "0x000000000000022D",
        "out-octets": "0x000000000000022D",
        "discontinuity-time": "2016-04-19T15:56:49Z",
        "out-discards": 0
      }
    },
    {
      "type": "link",
      "name": "A_NIC.tx -> A_Virtio.rx",
      "statistics": {
        "in-octets": "0x000000000000045A",
        "out-octets": "0x000000000000045A",
        "discontinuity-time": "2016-04-19T15:56:31Z",
        "out-discards": 0
      }
    },
    {
      "type": "link",
      "name": "B_Filter_in.tx -> B_Virtio.rx",
      "statistics": {
        "in-octets": "0x000000000000045A",
        "out-octets": "0x000000000000045A",
        "discontinuity-time": "2016-04-19T15:56:31Z",
        "out-discards": 0
      }
    },
    {
      "type": "virtual",
      "name": "B_Virtio",
      "statistics": {
        "in-octets": "0x0000000054D6F6D8",
        "out-multicast": "0x0000000000000001",
        "in-discards": 0,
        "in-multicast": "0x0000000000000008",
        "out-unicast": "0x0000000000EA4562",
        "in-unicast": "0x00000000004A9D28",
        "discontinuity-time": "2016-04-19T15:52:02Z",
        "out-octets": "0x0000000C651B8648"
      }
    },
    {
      "type": "hardware",
      "phys-address": "52:54:00:00:00:01",
      "name": "B_NIC",
      "statistics": {
        "in-octets": "0x0000000000000000",
        "out-octets": "0x0000000000000000",
        "discontinuity-time": "2016-04-19T15:52:02Z",
        "in-discards": 0
      }
    },
    {
      "type": "virtual",
      "name": "A_Virtio",
      "statistics": {
        "in-octets": "0x0000000C81A73BB6",
        "out-multicast": "0x0000000000000000",
        "in-discards": 0,
        "in-multicast": "0x0000000000000009",
        "out-unicast": "0x000000000046808F",
        "in-unicast": "0x0000000000EF0A89",
        "discontinuity-time": "2016-04-19T15:52:02Z",
        "out-octets": "0x000000003C3BDBF0"
      }
    },
    {
      "type": "hardware",
      "phys-address": "52:54:00:00:00:00",
      "name": "A_NIC",
      "statistics": {
        "in-octets": "0x0000000000000000",
        "out-octets": "0x0000000000000000",
        "discontinuity-time": "2016-04-19T15:52:02Z",
        "in-discards": 0
      }
    }
  ]
}

@wingo
Copy link
Contributor

wingo commented Apr 20, 2016

What's going on here? I thought Yang was being planned as part of #696. This seems to be much more ad-hoc with no design document.

@wingo
Copy link
Contributor

wingo commented Apr 20, 2016

I agree that JSON is probably not the best representation for this data, because YANG's set of data types does not map particularly well to JSON. For me you always need a schema for a computer to interpret YANG instance data, if you are not serializing in a representation that is compatible with the XML representation.

@lukego
Copy link
Member

lukego commented Apr 20, 2016

This is exciting to me as a big step in the direction of supporting standard RFC 7223 network interface statistics. This is the raw information that network operators need in order to monitor links in their networks. Having these counters available at all major points where packets ingress/egress from Snabb (e.g. NIC, VM, kernel, important tunnel, ...) would make it much easier to produce applications that are easy to monitor.

This is really only indirectly related to YANG i.e. the counters in RFC 7223 are spec'd as YANG objects and so to implement that you implicitly need to have some kind of mapping.

Figuring out the right way to connect this information with the various "northbound" interfaces - snabbtop, netsnmpd, netconf, etc - is the next discussion that I think @wingo has just started :-) and of course @alexandergall already has one such solution in tree here for intel10g and netsnmp.

Have only skimmed the code but looks good to me so far! I am really curious to know whether we will see a significant performance impact from things like counting unicast vs multicast packets in software when hardware counters are not available.

@wingo
Copy link
Contributor

wingo commented Apr 20, 2016

I definitely get the need for good counters :) Maybe I was just spooked by the name of the PR, especially given the long discussion on #696. I am using #696 as a base to start work on YANG in Snabb. Is that the wrong thing to do now? I am confused :)

@lukego
Copy link
Member

lukego commented Apr 20, 2016

Could consider s/YANG/netmod interface counters/ in the title.

I see this branch as primarily developing support for keeping track of counter values that are needed for populating some standard YANG models. This is kind of a big deal because it can involve inspecting the packet stream in apps that would otherwise be payload-agnostic e.g. the vhost_user app needing to check payload to decide whether to bump the unicast or multicast counter. Have to see what the overhead is here - and if it is high then whether any compromise makes sense.

These values will then be fed into the YANG framework that you are hacking based on #696. Meanwhile snabbtop is providing an interim interface for dumping the counters during development. This all has to be integrated together (and with existing SNMP support) once all the bits are there.

Make sense @eugeneia @wingo?

@plajjan
Copy link
Contributor

plajjan commented Apr 20, 2016

I don't immediately see the problem with using JSON. @wingo can you elaborate? There is https://tools.ietf.org/html/draft-ietf-netmod-yang-json-09 which defines a mapping for JSON so shouldn't be a problem with the types but I haven't really looked at the details. With that said, I don't really mind XML either.

As for the output itself the counter64 is hex encoded, why? counter64 is a uint64 and the mapping for that is described here - https://tools.ietf.org/html/draft-ietf-netmod-yang-json-09#section-6.1

The "type" is an identityref and current ones are described in rfc7224 - https://tools.ietf.org/html/rfc7224. I guess you can use existing values, like "ethernetCsmacd" where you currently have "hardware". For snabb specific stuff we need to create a new yang model that defines new identityrefs - like snabbLink.

@eugeneia eugeneia changed the title [wip] snabb top --yang: dump YANG model as JSON [wip] snabb top --yang: dump YANG-oriented interface stats as JSON Apr 20, 2016
@wingo
Copy link
Contributor

wingo commented Apr 20, 2016

@lukego: Makes sense to me, sure. Integrating all of this does have some unknowns, but sure.

@plajjan I can see the value of a JSON serialization when talking to a tool that expects the standard JSON YANG mapping and which also has the schema on-hand. Just dumping JSON without a schema is likely to run into problems as you note: #696 (comment).

But given that JSON is a fair bit of ceremony to parse, that it's hard to give good errors for a YANG JSON production (by the time you are validating the instance data you don't have source locations on-hand), that you have to shove numbers into strings, well at that point given that you have to build some representation of the schema in many YANG-processing places, then you might as well serialize using a nicer language (e.g. the text argument to the load_config example in #696 (comment)). You could then translate that minimal language to the XML representation using an external tool, so as not to deal with XML from Snabb.

Backing up.... it's easy to write out data in JSON. It's not so easy to consume it, when you factor in the types and the need to validate that instance data conforms to a schema. Snabb will need to validate configurations with good messages for the user to indicate when something is wrong with the configuration. I see JSON as being in the way of that goal -- not nice to write by hand, not nice to give errors for, does not support the data types we need. But I think this is more of a discussion for #696. This PR is limited to export of state data. A YANG integration in Snabb will have to import and export configuration data too.

@eugeneia
Copy link
Member Author

@wingo Sorry for the confusion/misleading title. This PR is 90% messing with counters and 10% thinking about how they might map to YAN, the JSON part is superficial.

@plajjan
Copy link
Contributor

plajjan commented Apr 20, 2016

@wingo I perceived this as a step in the right direction and not necessarily the final solution.

I assumed one would have the schema handy but you have probably thought more about the internals of implementing this in Snabb. Right now I can't spare the brain cycles to think about this and come up with any sensible input so I'll just leave it in your capable hands :)

IIRC XML (at least XML-RPC) also suffers from lack of large numbers, but maybe I'm thinking of > 64 bits.

@eugeneia eugeneia changed the title [wip] snabb top --yang: dump YANG-oriented interface stats as JSON [wip] snabb top --yang: dump RFC7223 interface stats as JSON Apr 20, 2016
@eugeneia
Copy link
Member Author

eugeneia commented Apr 20, 2016

@wingo So again to be clear, you are the lead on all things YANG. Consider snabb top --yang to be merely a stub that will be superseded by a more well-planned implementation.

Edit: Btw, most of the confusion probably came from me confusing RFC7223 with YANG. I hope I have fixed the terminology in the PR title/text.

@wingo
Copy link
Contributor

wingo commented Apr 20, 2016

@eugeneia all good by me, and the functionality of this patch is really excellent and quite welcome :) great stuff!

@@ -116,6 +148,11 @@ function Intel82599:push ()
end
end
self.dev:sync_transmit()
if self.dev.txstats then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How frequently do these counters need to be synchronized with hardware?

This code is synchronizing them every breath but that adds up to a significant number of PCIe accesses even e.g. for NICs that are completely idle. This may cause performance degradation in scenarios that we don't have CI performance coverage on at the moment e.g. app network with very many NICs where most are idle but some are active.

One alternative would be to use a timer to update every e.g. one millisecond.

Copy link
Member Author

@eugeneia eugeneia Apr 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, honestly I had/have trouble getting a good understanding of Intel10G stat registers code. Could definitely use a thorough review with SHM stats in mind (e.g. get rid of Intel10G.dev.get_rx/tx_stats() altogether). In this PR I attempted to be make mostly non-disruptive (light bolt-on) changes.

@wingo
Copy link
Contributor

wingo commented Apr 25, 2016

Related to your second point @eugeneia, how close to implementing this are you? If you can afford to wait a month, then I think we will have made some YANG progress in some way and it will be more clear how to represent YANG instance data coming from Snabb. I think that in our output language, we will need to be able to import modules and declare certain properties as being extensions, i.e.

namespace mib-ii-smi { default; }
namespace http://example.com/ethernet { prefix eth; }
// ...
interface { type hardware; eth:foo-property bar; }

Big-picture-wise we are defining a language whether we want to or not, whether it is built on JSON or otherwise, and it will have a grammar, and we should specify that grammar formally, and it should be extensible, and it should be pleasant to deal with. Could be based on json; I'd go for something more ad-hoc but ymmv. WDYT?

@eugeneia
Copy link
Member Author

@wingo I am just brainstorming from the statistics perspective, and write things down that I think might be relevant. I am mostly trying to find out which tasks are based on the Snabb-YANG model and which are independent. E.g. even without having the model defined, we can tell that

  • we already have an interface hierarchy in Intel10G that is currently ignored
  • there will be different statistics collected by different interface types

I absolutely want to wait for a your YANG spec for any mapping to that. At the same time I would like to get other issues out of the way in parallel. My next steps would be to:

  • dig into the Intel10G driver and think about how to expose the “super stat counters”
  • find out what is good practice regarding where to collect which statistics
  • (and then I see things like Standardise port names for NIC type apps #871 which I am thinking about extending to counter names, related janitorial changes, etc...)

Does that make sense to figure out these kinds of things in parallel?

Regarding JSON: disregard the mockup in this PR, I have no preference.

@wingo
Copy link
Contributor

wingo commented Apr 26, 2016

Yeah totes, working in parallel is great. I suspect that given that we need to end up with a coherent whole but that we have different focuses in the near term (you, AFAIU: exposing the RFC 7223 set of counters, me: exposing the YANG counters for the lwAFTR based on an internet draft, in addition to implementing some kind of minimal schema for consuming configuration and state data) that we will develop and figure out in parallel, and then reconcile in a few weeks. As long as we keep in close enough communication we could end up with a nice result. Let me know if I have misunderstood :) Perhaps we should have a tracker bug for conversations, given that you are not on Slack or IRC AFAIU.

@alexandergall
Copy link
Contributor

@eugeneia wrt if-index: I use a static mapping of PCI addresses to if-index (or ifIndex in SNMP-speak) for my SNMP agent, see https://github.com/alexandergall/snabb-snmp-subagent/blob/master/README.md#interface-subagent

I suggest you do the same.

@eugeneia
Copy link
Member Author

@alexandergall But not every interface has a PCI address? E.g. virtual interfaces, tunnel interfaces, ... I think this kind of indexing will have to be addressed in core.app.

@alexandergall
Copy link
Contributor

Ok, to be more precise then: in SNMP, the object ifDescr contains a textual identifier of an interface (e.g. "GigabitEthernet2/1" on a Cisco device, i use the PCI address for a physical interface). The mapping is from that name to the index. There must be an analogue to ifDescr in the YANG model.

@eugeneia
Copy link
Member Author

I realize now that I had overestimated the statistics provided by the 82599 NIC. There are actually just 16 register “groups” (see rx/txcounter options) for collecting stats. So it is not the case that every VMDq instance has its own statistics, but instead you have to allocate one for each and there are not enough groups for every instance. I suspect this feature is so obscure that it will be of limited use, and these restrictions make it unsuitable for collecting per-app statistics.

Where does that leave us? I am leaning towards exposing the per-PCI-address global statistics in counters/<pciaddr> and counting per-app statistics in software (possibly limited statistics visible). Alternatively per-app statistics could be only exposed by Intel10G apps that have rx/txcounter IDs (possibly complicated code).

@eugeneia
Copy link
Member Author

eugeneia commented May 13, 2016

@alexandergall I have added per-PCI address statistics SHM counters for Intel10G in f0ed10b, two observations:

  1. In this model, I would really like to expose relations between “counter groups” in SHM, e.g. it should be possible to inspect the counters of app “VQ_Intel_xyz”, and see that its parent is “0000:01:...”. This way it will be possible to relate the statistics of an app’s link to the respective hardware statistics. Since I need IDs for interfaces anyways, I am thinking it might be a good idea to implement these in a way compatible with YANG/Netconf.
  2. I have noticed this duplicates a lot of your ifTable MIB code from Rudimentary support of the ifTable MIB for intel10g #427. I would like to replace that code during this effort. This would mean scrapping lib.ipc and updating your client to use the shmem objects in /var/run/snabb that I promise will be a super-set of what you depend on. Thoughts?

@alexandergall
Copy link
Contributor

@eugeneia I can't comment much on the specific issue wrt VMDq stats. From the perspective of monitoring via NC/YANG or SNMP, it seems clear that every interface (irrespective of whether it's hardware or virtual) should be exposed by name/index (the primary handle for monitoring being the name).

I'm not sure how useful it is to be able to link a virtual interface to a physical one. If you do have dedicated counters, you expose them through the stats of the virtual interface and if you don't have them, the counters of the physical interface are more or less useless. At least with SNMP, there is a mechanism for this kind of mapping with the ifStackTable, though this is rarely used in practice. I don't know if there is a corresponding YANG model.

I must confess that I didn't follow this PR or #696 closely, so I applogize for not knowing what exactly has been discussed.

I would prefer if we had a more generic framework for exposing data for the purpose of monitoring which is not biased towards any particular northbound interface. I'm sure that you can't assume any kind of mapping between YANG models and SNMP MIBs in general. That would make it necessary to have another layer that would transform the raw data to something specific for each protocol.

For example, the lib.ipc.mib module is aware of data types specific to SNMP and this is part of the API for external programs that will consume this data (for example my SNMP subagents or snabb-top). Which brings me to your point 2. How much of lib.ipc.mib do you plan to support with this replacement? It's not just 64-bit counters and there is some tricky stuff related to time stamps in SNMP, see https://github.com/alexandergall/snabb-snmp-subagent#handling-of-the-snmp-timeticks-type.

Also, just getting the fields from RFC7223 wouldn't make me happy either. Not all of ifTable, ifXTable is mapped to objects in the YANG model. In particular, ifDesc is specifically excluded, but it is the de-facto standard field for interface names in many devices (Cisco for example), even if that is not RFC-compliant.

Also, I use lib.ipc.mib to manage other MIBs as well. May I ask you to keep lib.ipc until we have sorted this out? You can mark it as deprecated, so nobody uses it for new code.

@eugeneia
Copy link
Member Author

eugeneia commented May 31, 2016

@alexandergall My gripes is not with lib.ipc.* in general, but with its direct use in intel10g.lua. E.g. right now there are two statistics interfaces exposed by intel_app in this branch. I want to replace if the MIB interface with a more generic one.

I would prefer if we had a more generic framework for exposing data for the purpose of monitoring which is not biased towards any particular northbound interface. I'm sure that you can't assume any kind of mapping between YANG models and SNMP MIBs in general. That would make it necessary to have another layer that would transform the raw data to something specific for each protocol.

This is my point of view as well. I propose that we expose a super-set of RFC7223 counters with some simplifications. Different “readers” of our statistics interface will have to process the data to a specific format such as RFC7223 or ifMIB.

  • the only data type is uint64_t
  • the name of an interface is stored only in the directory structure (e.g. /var/run/snabb/<pid>/counters/<name>/<stat-counter>)
  • time/date is represented as seconds elapsed since epoch
  • I probably don't want to expose unicast packet counts but instead total packets / multicast / broadcast
  • I only want to expose fields that are actually implemented in a meaningful way. Readers must provide sensible defaults for fields that are not present.

If I implemented the schema described above, and refactored the code in M_sf:init_snmp into its own module, keeping the exact functionality intact, would that be OK for you?

@alexandergall
Copy link
Contributor

@eugeneia I basically agree but I'm not sure about the restriction to uint64_t and that everything is called a "counter". For example, timestamps, the physical MAC address or the operational status do fit into a uin64_t but they are not really counters. I find it confusing if they are labelled as such. Also, let's assume that I want to populate the ifName, ifDescr and ifAlias SNMP objects, which are strings and can all be different. How would I expose those? Through another branch in /var/run/snabb/<pid>? Which one?

I guess the question is related to how we want to organize the /var/run/snabb/<pid> directory (appologies if this has already been discussed and I missed it). I think I understand that you would like to treat interfaces controlled by a process equal to links between apps within that process at least wrt packet counters, but an interface is a more complex thing and it's also "system-wide unique". For my particular application, I don't even care which process controls the interface and it is easier to refer to a constant location, e.g., /var/run/snabb/interfaces/<name> (actually /var/lib/snabb/shmem in my current implementation) rather than having to track changes of the PID.

@eugeneia
Copy link
Member Author

eugeneia commented Jun 1, 2016

I don't want to restrict the available shmem data types to uint64_t, there will definitely be more data types in the future such as @lukego’s timeline. What I don't want to do is to implement data types like int32_t, gauge32, datetime, macaddr_t on the storage level when they all easily fit a data type that is already implemented.

Also, let's assume that I want to populate the ifName, ifDescr and ifAlias SNMP objects

Right now, just like higherLayerIf I suppose.

I guess the question is related to how we want to organize the /var/run/snabb/ directory

I am absolutely not set on the layout of /var/run/snabb. @lukego doesn't like that we reference instances by pid and I am starting to agree. The layout used currently will break down once apps can have shmem objects other than counters. So it will definitely change but I am not thinking about that too much right now because that's future problems.

@alexandergall
Copy link
Contributor

I don't want to restrict the available shmem data types to uint64_t, there will definitely be more data types in the future such as @lukego’s timeline. What I don't want to do is to implement data types like int32_t, gauge32, datetime, macaddr_t on the storage level when they all easily fit a data type that is already implemented.

I agree with that. What I'm saying is that we need something other than uint64_t even now (at least a sequence of bytes of variable size to store, for example, a string) and that labelling everything stored in a uint64_t as "counter" is a mistake.

Also, let's assume that I want to populate the ifName, ifDescr and ifAlias SNMP objects

Right now, just like higherLayerIf I suppose.

Which is done... how?

I guess the question is related to how we want to organize the /var/run/snabb/ directory

I am absolutely not set on the layout of /var/run/snabb. @lukego doesn't like that we reference instances by pid and I am starting to agree. The layout used currently will break down once apps can have shmem objects other than counters. So it will definitely change but I am not thinking about that too much right now because that's future problems.

Again: we already live in that future if we stop calling everything that fits into a uint64_t a counter :) I think that we should try to find a more flexible naming convention for /var/run/snabb now rather than using one which we already know will have to be changed. It shouldn't be too hard (famous last words :)

@lukego
Copy link
Member

lukego commented Jun 2, 2016

Just a related background point:

Currently we are allocating each shm object (e.g. counter) on a 4096-byte aligned address. This is not a valid design for x86. The problem is that the low 12 bits of the address will always be zero and this leads to "conflict misses" for Intel's set-associative cache. The CPU cache simply cannot contain many objects that have the same values in their low bits. See e.g. http://danluu.com/3c-conflict/.

This has already bitten us in practice. The workaround we made for now is to double-buffer counters so that we access a local cache of the value and then periodically commit that to the 4096-byte aligned shared memory address. This is complex and lacks generality.

So we need to come up with a new allocation scheme and ideally make the objects cheap to access by having more entropy in the low bits of their addresses. Simplest to implement might be to assign random padding to the beginning of the objects. However we may alternatively prefer a scheme that allocates many objects on the same page instead.

@eugeneia
Copy link
Member Author

eugeneia commented Jun 3, 2016

Here I attempted to find a common ground between RFC7223 and ifTable MIB: eugeneia/snabb@f4834a5...eugeneia:statistics-superset

This takes the SNMP code from intel10g.lua and moves it into its own module (using a common interface for app counters). Haven't tested it but theoretically init_snmp should work with other apps such as vhost_user as well. The caveat is that it is not automatically started by the intel app but must be manually started for a given app. This is a sketch.

Again: we already live in that future if we stop calling everything that fits into a uint64_t a counter :) I think that we should try to find a more flexible naming convention for /var/run/snabb now rather than using one which we already know will have to be changed. It shouldn't be too hard (famous last words :)

The reason I am reluctant to do this now is because I think requirements will be more clear when @wingo comes up with a model. Can't hurt to get started with what we know though!

Are there any data types we need to support besides uint64_t and byte strings? (digression: I am OK with the core.counter API for dealing with uint64_t, e.g. as an interface that has set, add and read. For some reason the name “counter” doesn't bother me much.)

Right now the directory structure is <type>/<object>/<instance-of-type>, e.g. adding a bytestring type could mean:

  • adding core.bytestring similar to core.counter
  • having bytestrings/<object>/<instance> in addition to counters/<object>/<instance>
  • make sure that when apps create counters/bytestrings they are created in the right directory

E.g. an app Foo_NIC could have a bytestring description at bytestrings/Foo_NIC/description and a counter txpackets at counters/Foo_NIC/txpackets.

The upside of the current layout is that readers of the shm directory can determine the type of a memory mapped object based on the layout. (That was my original motivation for this layout: to avoid having to encode types in the objects or map object names to types.)

The downside is that the directory structure is scattered. E.g. not a single directory containing all resources managed by an app.

Alternative ideas welcome!

@alexandergall
Copy link
Contributor

This takes the SNMP code from intel10g.lua and moves it into its own module (using a common interface for app counters). Haven't tested it but theoretically init_snmp should work with other apps such as vhost_user as well. The caveat is that it is not automatically started by the intel app but must be manually started for a given app. This is a sketch.

Something like this would certainly make sense. I don't worry about starting a separate process for this outside the Snabb framework (for my appliance, I would simply add another systemd serivce).

Are there any data types we need to support besides uint64_t and byte strings? (digression: I am OK with the core.counter API for dealing with uint64_t, e.g. as an interface that has set, add and read. For some reason the name “counter” doesn't bother me much.)

An array of uint64s might make sense. For example, I'm thinking about exposing the MAC table of the bridge app via the BRIDGE-MIB. Using separate "counters" for this could be excessive for large tables. The number of entries in the table would be determined by the size of the file.

Concerning the name "counter": why don't we simply call it uint64 (or just int or something), because that's what it actually is?

The upside of the current layout is that readers of the shm directory can determine the type of a memory mapped object based on the layout. (That was my original motivation for this layout: to avoid having to encode types in the objects or map object names to types.)

The downside is that the directory structure is scattered. E.g. not a single directory containing all resources managed by an app.

Alternative ideas welcome!

A simple alternative would be to add the type as an extension to the object's name. e.g. Foo_NIC/txpackets.counter (or Foo_NIC/txpackets.uint64 :)

If we want different views of the same data (per app, per object etc.) we could consider creating a hierarchy in /var/run/snabb consisting of symlinks to the actual data.

@eugeneia
Copy link
Member Author

This takes the SNMP code from intel10g.lua and moves it into its own module (using a common interface for app counters). Haven't tested it but theoretically init_snmp should work with other apps such as vhost_user as well. The caveat is that it is not automatically started by the intel app but must be manually started for a given app. This is a sketch.

Something like this would certainly make sense. I don't worry about starting a separate process for this outside the Snabb framework (for my appliance, I would simply add another systemd serivce).

The current code (merged in #931) is actually written to run in the same process. I aimed for a drop-in replacement.

An array of uint64s might make sense. For example, I'm thinking about exposing the MAC table of the bridge app via the BRIDGE-MIB. Using separate "counters" for this could be excessive for large tables. The number of entries in the table would be determined by the size of the file.

Hmm that seems awful specific. I will look into making core.shm more generic to allow for variable length types so that these types of uses are possible.

Concerning the name "counter": why don't we simply call it uint64 (or just int or something), because that's what it actually is?

From my point of view uint64_t is the data type while core.counter is a specific API including fancy things like double buffering. I would argue core.counter is 90% a problem specific API and only 10% a uint64_t.

A simple alternative would be to add the type as an extension to the object's name. e.g. Foo_NIC/txpackets.counter (or Foo_NIC/txpackets.uint64 :)

I like that idea!

@alexandergall
Copy link
Contributor

The current code (merged in #931) is actually written to run in the same process. I aimed for a drop-in replacement.

Nice. I suppose I would then do something like

  init_snmp(..., engine.app_table[Intel82599].counters, ...)

before running the engine?

Concerning the name "counter": why don't we simply call it uint64 (or just int or something), because that's what it actually is?

From my point of view uint64_t is the data type while core.counter is a specific API including fancy things like double buffering. I would argue core.counter is 90% a problem specific API and only 10% a uint64_t.

Another approach would be to implement a API for storing a simple number (e.g. the interface administrative status) which doesn't need any of the fancy stuff and specialize for the semantics of a counter where you need it. Probably violates the KISS principle :) Anyway, it's not terribly important and I'll stop arguing about it.

@eugeneia
Copy link
Member Author

Nice. I suppose I would then do something like

init_snmp(..., engine.app_table[Intel82599].counters, ...)

before running the engine?

Exactly. :-) I haven't tested the code but I have been careful about maintaining semantics.

@eugeneia eugeneia merged commit b09e843 into snabbco:master Jul 13, 2016
takikawa pushed a commit to takikawa/snabb that referenced this pull request Aug 5, 2017
Unify lwAFTR and other state query around YANG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants