diff --git a/src/apps/socket/raw.lua b/src/apps/socket/raw.lua index 13ecb8d635..45d6b5ddce 100644 --- a/src/apps/socket/raw.lua +++ b/src/apps/socket/raw.lua @@ -80,12 +80,8 @@ function RawSocket:receive () p.length = sz counter.add(self.shm.rxbytes, sz) counter.add(self.shm.rxpackets) - if ethernet:is_mcast(p.data) then - counter.add(self.shm.rxmcast) - end - if ethernet:is_bcast(p.data) then - counter.add(self.shm.rxbcast) - end + counter.add(self.shm.rxmcast, ethernet:n_mcast(p.data)) + counter.add(self.shm.rxbcast, ethernet:n_bcast(p.data)) return packet.clone(p) end @@ -97,12 +93,8 @@ function RawSocket:push () self:transmit(p) counter.add(self.shm.txbytes, p.length) counter.add(self.shm.txpackets) - if ethernet:is_mcast(p.data) then - counter.add(self.shm.txmcast) - end - if ethernet:is_bcast(p.data) then - counter.add(self.shm.txbcast) - end + counter.add(self.shm.txmcast, ethernet:n_mcast(p.data)) + counter.add(self.shm.txbcast, ethernet:n_bcast(p.data)) packet.free(p) end end diff --git a/src/apps/tap/tap.lua b/src/apps/tap/tap.lua index f0fb97bc98..3e06b559cc 100644 --- a/src/apps/tap/tap.lua +++ b/src/apps/tap/tap.lua @@ -62,12 +62,8 @@ function Tap:pull () link.transmit(l, p) counter.add(self.shm.rxbytes, len) counter.add(self.shm.rxpackets) - if ethernet:is_mcast(p.data) then - counter.add(self.shm.rxmcast) - end - if ethernet:is_bcast(p.data) then - counter.add(self.shm.rxbcast) - end + counter.add(self.shm.rxmcast, ethernet:n_mcast(p.data)) + counter.add(self.shm.rxbcast, ethernet:n_bcast(p.data)) end end @@ -87,12 +83,8 @@ function Tap:push () end counter.add(self.shm.txbytes, len) counter.add(self.shm.txpackets) - if ethernet:is_mcast(p.data) then - counter.add(self.shm.txmcast) - end - if ethernet:is_bcast(p.data) then - counter.add(self.shm.txbcast) - end + counter.add(self.shm.txmcast, ethernet:n_mcast(p.data)) + counter.add(self.shm.txbcast, ethernet:n_bcast(p.data)) -- The write completed so dequeue it from the link and free the packet link.receive(l) packet.free(p) diff --git a/src/apps/vhost/vhost_user.lua b/src/apps/vhost/vhost_user.lua index 72df66cba2..418f6f81e6 100644 --- a/src/apps/vhost/vhost_user.lua +++ b/src/apps/vhost/vhost_user.lua @@ -13,6 +13,7 @@ local lib = require("core.lib") local link = require("core.link") local main = require("core.main") local memory = require("core.memory") +local counter = require("core.counter") local pci = require("lib.hardware.pci") local net_device= require("lib.virtio.net_device") local timer = require("core.timer") @@ -41,7 +42,17 @@ function VhostUser:new (args) function () self:process_qemu_requests() end, 5e8,-- 500 ms 'non-repeating' - ) + ), + -- counters + shm = { rxbytes = {counter}, + rxpackets = {counter}, + rxmcast = {counter}, + rxbcast = {counter}, + rxdrop = {counter}, + txbytes = {counter}, + txpackets = {counter}, + txmcast = {counter}, + txbcast = {counter} } } self = setmetatable(o, {__index = VhostUser}) self.dev = net_device.VirtioNetDevice:new(self, diff --git a/src/lib/protocol/README.md b/src/lib/protocol/README.md index 8c237dcf6f..829d272812 100644 --- a/src/lib/protocol/README.md +++ b/src/lib/protocol/README.md @@ -102,10 +102,20 @@ Returns the string representation of *mac* address. Returns a true value if *mac* address denotes a [Multicast address](https://en.wikipedia.org/wiki/Multicast_address#Ethernet). +— Function **ethernet:n_mcast** *mac* + +Returns 1 if *mac* address denotes a [Multicast address](https://en.wikipedia.org/wiki/Multicast_address#Ethernet) +and 0 otherwise. + — Function **ethernet:is_bcast** *mac* Returns a true value if *mac* address denotes a [Broadcast address](https://en.wikipedia.org/wiki/Broadcast_address#Ethernet). +— Function **ethernet:n_bcast** *mac* + +Returns 1 if *mac* address denotes a [Broadcast address](https://en.wikipedia.org/wiki/Broadcast_address#Ethernet) +and 0 otherwise. + — Function **ethernet:ipv6_mcast** *ip* Returns the MAC address for IPv6 multicast *ip* as defined by RFC2464, diff --git a/src/lib/protocol/ethernet.lua b/src/lib/protocol/ethernet.lua index c874f35acb..b237027f6f 100644 --- a/src/lib/protocol/ethernet.lua +++ b/src/lib/protocol/ethernet.lua @@ -6,8 +6,9 @@ local C = ffi.C local lib = require("core.lib") local header = require("lib.protocol.header") local ipv6 = require("lib.protocol.ipv6") -local band = require("bit").band local ntohs, htons = lib.ntohs, lib.htons +local abs, min = math.abs, math.min +local band, bxor = bit.band, bit.bxor local mac_addr_t = ffi.typeof("uint8_t[6]") local ethernet = subClass(header) @@ -76,15 +77,26 @@ function ethernet:ipv6_mcast(ip) return result end +-- Return 1 if MAC address has its group bit set and 0 otherwise +function ethernet:n_mcast (addr) + return band(addr[0], 0x01) +end + -- Check whether a MAC address has its group bit set function ethernet:is_mcast (addr) - return band(addr[0], 0x01) ~= 0 + return ethernet:n_mcast(addr) == 1 +end + +-- Return 1 if MAC address is the broadcast address and 0 otherwise +function ethernet:n_bcast (addr) + local bcast = abs(bxor(0xFFFFFFFF, ffi.cast("uint32_t*", addr)[0])) + bcast = bcast + abs(bxor(0xFFFF, ffi.cast("uint16_t*", addr)[2])) + return 1 - min(bcast, 1) end -local bcast_address = ethernet:pton("FF:FF:FF:FF:FF:FF") -- Check whether a MAC address is the broadcast address function ethernet:is_bcast (addr) - return C.memcmp(addr, bcast_address, 6) == 0 + return ethernet:n_bcast(addr) == 1 end -- Instance methods diff --git a/src/lib/virtio/net_device.lua b/src/lib/virtio/net_device.lua index 10164d3a11..6a16447650 100644 --- a/src/lib/virtio/net_device.lua +++ b/src/lib/virtio/net_device.lua @@ -11,6 +11,8 @@ local memory = require("core.memory") local packet = require("core.packet") local timer = require("core.timer") local VirtioVirtq = require("lib.virtio.virtq_device") +local counter = require("core.counter") +local ethernet = require("lib.protocol.ethernet") local checksum = require("lib.checksum") local ffi = require("ffi") local C = ffi.C @@ -154,6 +156,7 @@ end function VirtioNetDevice:rx_packet_end(header_id, total_size, rx_p) local l = self.owner.output.tx + local counters = self.owner.shm if l then if band(self.rx_hdr_flags, C.VIO_NET_HDR_F_NEEDS_CSUM) ~= 0 and -- Bounds-check the checksum area @@ -165,9 +168,14 @@ function VirtioNetDevice:rx_packet_end(header_id, total_size, rx_p) rx_p.length - self.rx_hdr_csum_start, self.rx_hdr_csum_offset) end + counter.add(counters.rxbytes, rx_p.length) + counter.add(counters.rxpackets) + counter.add(counters.rxmcast, ethernet:n_mcast(rx_p.data)) + counter.add(counters.rxbcast, ethernet:n_bcast(rx_p.data)) link.transmit(l, rx_p) else debug("droprx", "len", rx_p.length) + counter.add(counters.rxdrop) packet.free(rx_p) end self.virtq[self.ring_id]:put_buffer(header_id, total_size) @@ -255,6 +263,11 @@ function VirtioNetDevice:tx_buffer_add(tx_p, addr, len) end function VirtioNetDevice:tx_packet_end(header_id, total_size, tx_p) + local counters = self.owner.shm + counter.add(counters.txbytes, tx_p.length) + counter.add(counters.txpackets) + counter.add(counters.txmcast, ethernet:n_mcast(tx_p.data)) + counter.add(counters.txbcast, ethernet:n_bcast(tx_p.data)) packet.free(tx_p) self.virtq[self.ring_id]:put_buffer(header_id, total_size) end @@ -326,8 +339,13 @@ function VirtioNetDevice:tx_buffer_add_mrg_rxbuf(tx_p, addr, len) end function VirtioNetDevice:tx_packet_end_mrg_rxbuf(header_id, total_size, tx_p) + local counters = self.owner.shm -- free the packet only when all its data is processed if self.tx.finished then + counter.add(counters.txbytes, tx_p.length) + counter.add(counters.txpackets) + counter.add(counters.txmcast, ethernet:n_mcast(tx_p.data)) + counter.add(counters.txbcast, ethernet:n_bcast(tx_p.data)) packet.free(tx_p) self.tx.p = nil self.tx.data_sent = nil