Skip to content

Commit

Permalink
Add XSKMAP support (iovisor#2730)
Browse files Browse the repository at this point in the history
* add XSKMAP support
* enable lookup for XSKMAP available from kernel 5.3
* add section for XSKMAP in reference guide
  • Loading branch information
tu-nv committed Jan 31, 2020
1 parent 0e63c5c commit 46965c6
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 28 deletions.
63 changes: 40 additions & 23 deletions docs/reference_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,17 @@ This guide is incomplete. If something feels missing, check the bcc and kernel s
- [9. BPF_PROG_ARRAY](#9-bpf_prog_array)
- [10. BPF_DEVMAP](#10-bpf_devmap)
- [11. BPF_CPUMAP](#11-bpf_cpumap)
- [12. map.lookup()](#12-maplookup)
- [13. map.lookup_or_try_init()](#13-maplookup_or_try_init)
- [14. map.delete()](#14-mapdelete)
- [15. map.update()](#15-mapupdate)
- [16. map.insert()](#16-mapinsert)
- [17. map.increment()](#17-mapincrement)
- [18. map.get_stackid()](#18-mapget_stackid)
- [19. map.perf_read()](#19-mapperf_read)
- [20. map.call()](#20-mapcall)
- [21. map.redirect_map()](#21-mapredirect_map)
- [12. BPF_XSKMAP](#12-bpf_xskmap)
- [13. map.lookup()](#13-maplookup)
- [14. map.lookup_or_try_init()](#14-maplookup_or_try_init)
- [15. map.delete()](#15-mapdelete)
- [16. map.update()](#16-mapupdate)
- [17. map.insert()](#17-mapinsert)
- [18. map.increment()](#18-mapincrement)
- [19. map.get_stackid()](#19-mapget_stackid)
- [20. map.perf_read()](#20-mapperf_read)
- [21. map.call()](#21-mapcall)
- [22. map.redirect_map()](#22-mapredirect_map)
- [Licensing](#licensing)

- [bcc Python](#bcc-python)
Expand Down Expand Up @@ -759,7 +760,23 @@ Methods (covered later): map.redirect_map().
Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=BPF_CPUMAP+path%3Aexamples&type=Code),
### 12. BPF_ARRAY_OF_MAPS
### 12. BPF_XSKMAP
Syntax: ```BPF_XSKMAP(name, size)```

This creates a xsk map named ```name``` with ```size``` entries. Each entry represents one NIC's queue id. This map is only used in XDP to redirect packet to an AF_XDP socket. If the AF_XDP socket is binded to a queue which is different than the current packet's queue id, the packet will be dropped. For kernel v5.3 and latter, `lookup` method is available and can be used to check whether and AF_XDP socket is available for the current packet's queue id. More details at [AF_XDP](https://www.kernel.org/doc/html/latest/networking/af_xdp.html).

For example:
```C
BPF_XSKMAP(xsks_map, 8);
```
Methods (covered later): map.redirect_map(). map.lookup()
Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=BPF_XSKMAP+path%3Aexamples&type=Code),
### 13. BPF_ARRAY_OF_MAPS
Syntax: ```BPF_ARRAY_OF_MAPS(name, inner_map_name, size)```

Expand All @@ -772,7 +789,7 @@ BPF_TABLE("hash", int, int, ex2, 1024);
BPF_ARRAY_OF_MAPS(maps_array, "ex1", 10);
```
### 13. BPF_HASH_OF_MAPS
### 14. BPF_HASH_OF_MAPS
Syntax: ```BPF_HASH_OF_MAPS(name, inner_map_name, size)```

Expand All @@ -785,7 +802,7 @@ BPF_ARRAY(ex2, int, 1024);
BPF_HASH_OF_MAPS(maps_hash, "ex1", 10);
```
### 14. map.lookup()
### 15. map.lookup()
Syntax: ```*val map.lookup(&key)```

Expand All @@ -795,7 +812,7 @@ Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=lookup+path%3Aexamples&type=Code),
[search /tools](https://github.com/iovisor/bcc/search?q=lookup+path%3Atools&type=Code)

### 15. map.lookup_or_try_init()
### 16. map.lookup_or_try_init()

Syntax: ```*val map.lookup_or_try_init(&key, &zero)```

Expand All @@ -808,7 +825,7 @@ Examples in situ:
Note: The old map.lookup_or_init() may cause return from the function, so lookup_or_try_init() is recommended as it
does not have this side effect.

### 16. map.delete()
### 17. map.delete()

Syntax: ```map.delete(&key)```

Expand All @@ -818,7 +835,7 @@ Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=delete+path%3Aexamples&type=Code),
[search /tools](https://github.com/iovisor/bcc/search?q=delete+path%3Atools&type=Code)

### 17. map.update()
### 18. map.update()

Syntax: ```map.update(&key, &val)```

Expand All @@ -828,7 +845,7 @@ Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=update+path%3Aexamples&type=Code),
[search /tools](https://github.com/iovisor/bcc/search?q=update+path%3Atools&type=Code)

### 18. map.insert()
### 19. map.insert()

Syntax: ```map.insert(&key, &val)```

Expand All @@ -838,7 +855,7 @@ Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=insert+path%3Aexamples&type=Code),
[search /tools](https://github.com/iovisor/bcc/search?q=insert+path%3Atools&type=Code)

### 19. map.increment()
### 20. map.increment()

Syntax: ```map.increment(key[, increment_amount])```

Expand All @@ -848,7 +865,7 @@ Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=increment+path%3Aexamples&type=Code),
[search /tools](https://github.com/iovisor/bcc/search?q=increment+path%3Atools&type=Code)

### 20. map.get_stackid()
### 21. map.get_stackid()

Syntax: ```int map.get_stackid(void *ctx, u64 flags)```

Expand All @@ -858,7 +875,7 @@ Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?q=get_stackid+path%3Aexamples&type=Code),
[search /tools](https://github.com/iovisor/bcc/search?q=get_stackid+path%3Atools&type=Code)

### 21. map.perf_read()
### 22. map.perf_read()

Syntax: ```u64 map.perf_read(u32 cpu)```

Expand All @@ -867,7 +884,7 @@ This returns the hardware performance counter as configured in [5. BPF_PERF_ARRA
Examples in situ:
[search /tests](https://github.com/iovisor/bcc/search?q=perf_read+path%3Atests&type=Code)

### 22. map.call()
### 23. map.call()

Syntax: ```void map.call(void *ctx, int index)```

Expand Down Expand Up @@ -906,11 +923,11 @@ Examples in situ:
[search /examples](https://github.com/iovisor/bcc/search?l=C&q=call+path%3Aexamples&type=Code),
[search /tests](https://github.com/iovisor/bcc/search?l=C&q=call+path%3Atests&type=Code)

### 23. map.redirect_map()
### 24. map.redirect_map()

Syntax: ```int map.redirect_map(int index, int flags)```

This redirects the incoming packets based on the ```index``` entry. If the map is [10. BPF_DEVMAP](#10-bpf_devmap), the packet will be sent to the transmit queue of the network interface that the entry points to. If the map is [11. BPF_CPUMAP](#11-bpf_cpumap), the packet will be sent to the ring buffer of the ```index``` CPU and be processed by the CPU later.
This redirects the incoming packets based on the ```index``` entry. If the map is [10. BPF_DEVMAP](#10-bpf_devmap), the packet will be sent to the transmit queue of the network interface that the entry points to. If the map is [11. BPF_CPUMAP](#11-bpf_cpumap), the packet will be sent to the ring buffer of the ```index``` CPU and be processed by the CPU later. If the map is [12. BPF_XSKMAP](#12-bpf_xskmap), the packet will be sent to the AF_XDP socket attached to the queue.

If the packet is redirected successfully, the function will return XDP_REDIRECT. Otherwise, it will return XDP_ABORTED to discard the packet.

Expand Down
7 changes: 7 additions & 0 deletions src/cc/api/BPF.cc
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,13 @@ BPFDevmapTable BPF::get_devmap_table(const std::string& name) {
return BPFDevmapTable({});
}

BPFXskmapTable BPF::get_xskmap_table(const std::string& name) {
TableStorage::iterator it;
if (bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it))
return BPFXskmapTable(it->second);
return BPFXskmapTable({});
}

BPFStackTable BPF::get_stack_table(const std::string& name, bool use_debug_file,
bool check_debug_file_crc) {
TableStorage::iterator it;
Expand Down
2 changes: 2 additions & 0 deletions src/cc/api/BPF.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ class BPF {

BPFDevmapTable get_devmap_table(const std::string& name);

BPFXskmapTable get_xskmap_table(const std::string& name);

BPFStackTable get_stack_table(const std::string& name,
bool use_debug_file = true,
bool check_debug_file_crc = true);
Expand Down
35 changes: 31 additions & 4 deletions src/cc/api/BPFTable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -627,21 +627,21 @@ StatusTuple BPFCgroupArray::remove_value(const int& index) {
return StatusTuple(0);
}

BPFDevmapTable::BPFDevmapTable(const TableDesc& desc)
BPFDevmapTable::BPFDevmapTable(const TableDesc& desc)
: BPFTableBase<int, int>(desc) {
if(desc.type != BPF_MAP_TYPE_DEVMAP)
throw std::invalid_argument("Table '" + desc.name +
throw std::invalid_argument("Table '" + desc.name +
"' is not a devmap table");
}

StatusTuple BPFDevmapTable::update_value(const int& index,
StatusTuple BPFDevmapTable::update_value(const int& index,
const int& value) {
if (!this->update(const_cast<int*>(&index), const_cast<int*>(&value)))
return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
return StatusTuple(0);
}

StatusTuple BPFDevmapTable::get_value(const int& index,
StatusTuple BPFDevmapTable::get_value(const int& index,
int& value) {
if (!this->lookup(const_cast<int*>(&index), &value))
return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
Expand All @@ -654,6 +654,33 @@ StatusTuple BPFDevmapTable::remove_value(const int& index) {
return StatusTuple(0);
}

BPFXskmapTable::BPFXskmapTable(const TableDesc& desc)
: BPFTableBase<int, int>(desc) {
if(desc.type != BPF_MAP_TYPE_XSKMAP)
throw std::invalid_argument("Table '" + desc.name +
"' is not a xskmap table");
}

StatusTuple BPFXskmapTable::update_value(const int& index,
const int& value) {
if (!this->update(const_cast<int*>(&index), const_cast<int*>(&value)))
return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
return StatusTuple(0);
}

StatusTuple BPFXskmapTable::get_value(const int& index,
int& value) {
if (!this->lookup(const_cast<int*>(&index), &value))
return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
return StatusTuple(0);
}

StatusTuple BPFXskmapTable::remove_value(const int& index) {
if (!this->remove(const_cast<int*>(&index)))
return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
return StatusTuple(0);
}

BPFMapInMapTable::BPFMapInMapTable(const TableDesc& desc)
: BPFTableBase<int, int>(desc) {
if(desc.type != BPF_MAP_TYPE_ARRAY_OF_MAPS &&
Expand Down
11 changes: 10 additions & 1 deletion src/cc/api/BPFTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,16 @@ class BPFCgroupArray : public BPFTableBase<int, int> {
class BPFDevmapTable : public BPFTableBase<int, int> {
public:
BPFDevmapTable(const TableDesc& desc);


StatusTuple update_value(const int& index, const int& value);
StatusTuple get_value(const int& index, int& value);
StatusTuple remove_value(const int& index);
};

class BPFXskmapTable : public BPFTableBase<int, int> {
public:
BPFXskmapTable(const TableDesc& desc);

StatusTuple update_value(const int& index, const int& value);
StatusTuple get_value(const int& index, int& value);
StatusTuple remove_value(const int& index);
Expand Down
12 changes: 12 additions & 0 deletions src/cc/export/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,18 @@ struct _name##_table_t _name = { .max_entries = (_max_entries) }
#define BPF_CPUMAP(_name, _max_entries) \
BPF_XDP_REDIRECT_MAP("cpumap", u32, _name, _max_entries)

#define BPF_XSKMAP(_name, _max_entries) \
struct _name##_table_t { \
u32 key; \
int leaf; \
int * (*lookup) (int *); \
/* xdp_act = map.redirect_map(index, flag) */ \
u64 (*redirect_map) (int, int); \
u32 max_entries; \
}; \
__attribute__((section("maps/xskmap"))) \
struct _name##_table_t _name = { .max_entries = (_max_entries) }

#define BPF_ARRAY_OF_MAPS(_name, _inner_map_name, _max_entries) \
BPF_TABLE("array_of_maps$" _inner_map_name, int, int, _name, _max_entries)

Expand Down
2 changes: 2 additions & 0 deletions src/cc/frontends/clang/b_frontend_action.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,8 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
map_type = BPF_MAP_TYPE_DEVMAP;
} else if (section_attr == "maps/cpumap") {
map_type = BPF_MAP_TYPE_CPUMAP;
} else if (section_attr == "maps/xskmap") {
map_type = BPF_MAP_TYPE_XSKMAP;
} else if (section_attr == "maps/hash_of_maps") {
map_type = BPF_MAP_TYPE_HASH_OF_MAPS;
} else if (section_attr == "maps/array_of_maps") {
Expand Down
6 changes: 6 additions & 0 deletions src/python/bcc/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ def Table(bpf, map_id, map_fd, keytype, leaftype, name, **kwargs):
t = DevMap(bpf, map_id, map_fd, keytype, leaftype)
elif ttype == BPF_MAP_TYPE_CPUMAP:
t = CpuMap(bpf, map_id, map_fd, keytype, leaftype)
elif ttype == BPF_MAP_TYPE_XSKMAP:
t = XskMap(bpf, map_id, map_fd, keytype, leaftype)
elif ttype == BPF_MAP_TYPE_ARRAY_OF_MAPS:
t = MapInMapArray(bpf, map_id, map_fd, keytype, leaftype)
elif ttype == BPF_MAP_TYPE_HASH_OF_MAPS:
Expand Down Expand Up @@ -905,6 +907,10 @@ class CpuMap(ArrayBase):
def __init__(self, *args, **kwargs):
super(CpuMap, self).__init__(*args, **kwargs)

class XskMap(ArrayBase):
def __init__(self, *args, **kwargs):
super(XskMap, self).__init__(*args, **kwargs)

class MapInMapArray(ArrayBase):
def __init__(self, *args, **kwargs):
super(MapInMapArray, self).__init__(*args, **kwargs)
Expand Down

0 comments on commit 46965c6

Please sign in to comment.