summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Kochan <vadim4j@gmail.com>2016-09-22 23:55:33 +0300
committerTobias Klauser <tklauser@distanz.ch>2016-10-04 17:17:24 +0200
commitf4c1856026c0edcc1e2285cf6ae773057bee51cd (patch)
treebaf5663ef7daf90b5f1cdd4c3e9f31868034238d
parent7007975949f5177fbf2514633cc44ba0ac4712c5 (diff)
trafgen: l2: Add support for IEEE 802.3X PAUSE header
Add EEE802.3X Ethernet MAC Control PAUSE frame proto header with two fields - opcode & time. By default Ethernet header is pushed on header init. Signed-off-by: Vadim Kochan <vadim4j@gmail.com> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r--trafgen_l2.c27
-rw-r--r--trafgen_l2.h5
-rw-r--r--trafgen_proto.h1
3 files changed, 33 insertions, 0 deletions
diff --git a/trafgen_l2.c b/trafgen_l2.c
index 866559c..8d2d285 100644
--- a/trafgen_l2.c
+++ b/trafgen_l2.c
@@ -30,6 +30,8 @@ static uint16_t pid_to_eth(enum proto_id pid)
return ETH_P_MPLS_UC;
case PROTO_VLAN:
return ETH_P_8021Q;
+ case PROTO_PAUSE:
+ return ETH_P_PAUSE;
default:
bug();
}
@@ -54,6 +56,30 @@ static const struct proto_ops eth_proto_ops = {
.set_next_proto = eth_set_next_proto,
};
+static struct proto_field pause_fields[] = {
+ { .id = PAUSE_OPCODE, .len = 2, .offset = 0 },
+ { .id = PAUSE_TIME, .len = 2, .offset = 2 },
+};
+
+static void pause_header_init(struct proto_hdr *hdr)
+{
+ uint8_t eth_dst[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x01 };
+
+ struct proto_hdr *lower;
+
+ lower = proto_lower_default_add(hdr, PROTO_ETH);
+ proto_field_set_default_bytes(lower, ETH_DST_ADDR, eth_dst);
+
+ proto_header_fields_add(hdr, pause_fields, array_size(pause_fields));
+ proto_field_set_default_be16(hdr, PAUSE_OPCODE, 0x1);
+}
+
+static struct proto_ops pause_proto_ops = {
+ .id = PROTO_PAUSE,
+ .layer = PROTO_L2,
+ .header_init = pause_header_init,
+};
+
static struct proto_field vlan_fields[] = {
/* TPID overlaps with Ethernet header and points to ether type */
{ .id = VLAN_TPID, .len = 2, .offset = -2 },
@@ -167,6 +193,7 @@ static const struct proto_ops mpls_proto_ops = {
void protos_l2_init(void)
{
proto_ops_register(&eth_proto_ops);
+ proto_ops_register(&pause_proto_ops);
proto_ops_register(&vlan_proto_ops);
proto_ops_register(&arp_proto_ops);
proto_ops_register(&mpls_proto_ops);
diff --git a/trafgen_l2.h b/trafgen_l2.h
index 14f0e84..7c8ef7d 100644
--- a/trafgen_l2.h
+++ b/trafgen_l2.h
@@ -7,6 +7,11 @@ enum eth_field {
ETH_TYPE,
};
+enum pause_field {
+ PAUSE_OPCODE,
+ PAUSE_TIME,
+};
+
enum arp_field {
ARP_HTYPE,
ARP_PTYPE,
diff --git a/trafgen_proto.h b/trafgen_proto.h
index a8b97eb..a1f6b66 100644
--- a/trafgen_proto.h
+++ b/trafgen_proto.h
@@ -8,6 +8,7 @@
enum proto_id {
PROTO_NONE = 0,
PROTO_ETH,
+ PROTO_PAUSE,
PROTO_VLAN,
PROTO_ARP,
PROTO_MPLS,