Compare commits

...

1 Commits

Author SHA1 Message Date
Markus Gothe
71943e17af MPLS: initial check-in. 2024-12-28 20:10:41 +01:00
4 changed files with 167 additions and 0 deletions

47
ebtables-mpls/Makefile Normal file
View File

@@ -0,0 +1,47 @@
#
# Copyright (C) 2024 IOPSYS Software Solutions AB
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=lre-mpls
PKG_VERSION:=1.0.0
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define KernelPackage/ebtables-mpls
SUBMENU:=Other modules
TITLE:=Kernel module for ebtables MPLS LER
FILES:=$(PKG_BUILD_DIR)/ebt_mpls.ko
DEPENDS+=+kmod-ebtables +ebtables-legacy
AUTOLOAD:=$(call AutoLoad,30,ebt_mpls,1)
KCONFIG:=
endef
define KernelPackage/ebtables-mpls/description
Kernel module to enable MPLS support for ebtables
endef
ifeq ($(CONFIG_TARGET_brcmbca),y)
include ../../broadcom/bcmkernel/bcm-kernel-toolchain.mk
endif
define Build/Prepare
$(CP) -rf ./src/* $(PKG_BUILD_DIR)/
$(CP) $(PKG_BUILD_DIR)/ebt_mpls.h $(LINUX_DIR)/include/uapi/linux/netfilter_bridge/
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/include/uapi/linux/netfilter_bridge/
$(CP) $(PKG_BUILD_DIR)/ebt_mpls.h $(1)/include/uapi/linux/netfilter_bridge/
endef
KERNEL_MAKE_FLAGS += -I$(LINUX_DIR)/include
define Build/Compile
$(KERNEL_MAKE) M="$(PKG_BUILD_DIR)" modules
endef
$(eval $(call KernelPackage,ebtables-mpls))

View File

@@ -0,0 +1 @@
obj-m += ebt_mpls.o

View File

@@ -0,0 +1,91 @@
/*
* ebt_mpls
*
* Authors:
* Markus Gothe <markus.gothe@genexis.eu>
*
* January, 2025
*
* SPDX-License-Identifier: GPL-2.0
*/
#include <linux/module.h>
#include <linux/if_vlan.h>
#include <linux/if_ether.h>
#include <linux/skbuff.h>
#include <linux/etherdevice.h>
#include <linux/netfilter.h>
#include <net/mpls.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_mpls.h>
#include <net/netfilter/br_netfilter.h>
static unsigned int ebt_mpls_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct ebt_mpls_info *info = par->targinfo;
if (info->decap && eth_p_mpls(eth_hdr(skb)->h_proto) && mpls_hdr(skb)->label_stack_entry == info->label) {
skb_push(skb, ETH_HLEN);
if (skb_mpls_pop(skb, info->protocol, ETH_HLEN, true))
return EBT_DROP;
skb_pull(skb, ETH_HLEN);
skb_reset_mac_len(skb);
} else if (eth_hdr(skb)->h_proto == info->protocol) {
skb_push(skb, ETH_HLEN);
if (skb_mpls_push(skb, info->label, info->multicast ? htons(ETH_P_MPLS_MC) : htons(ETH_P_MPLS_UC), ETH_HLEN, true))
return EBT_DROP;
skb_pull(skb, ETH_HLEN);
skb_reset_mac_len(skb);
}
return info->target;
}
static int ebt_mpls_tg_check(const struct xt_tgchk_param *par)
{
const struct ebt_mpls_info *info = par->targinfo;
unsigned int hook_mask;
if (BASE_CHAIN && info->target == EBT_RETURN)
return -EINVAL;
hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS);
if ((strcmp(par->table, "nat") != 0 || hook_mask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_POST_ROUTING) | (1 << NF_BR_LOCAL_OUT))) &&
(strcmp(par->table, "broute") != 0 || hook_mask & ~(1 << NF_BR_BROUTING)) &&
(strcmp(par->table, "filter") != 0 || hook_mask & ~(1 << NF_BR_LOCAL_IN)))
return -EINVAL;
if (ebt_invalid_target(info->target))
return -EINVAL;
return 0;
}
static struct xt_target ebt_mpls_tg_reg __read_mostly = {
.name = "mpls",
.revision = 0,
.family = NFPROTO_BRIDGE,
.hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_POST_ROUTING) | (1 << NF_BR_LOCAL_OUT) | (1 << NF_BR_LOCAL_IN) | (1 << NF_BR_BROUTING),
.target = ebt_mpls_tg,
.checkentry = ebt_mpls_tg_check,
.targetsize = sizeof(struct ebt_mpls_info),
.me = THIS_MODULE,
};
static int __init ebt_mpls_init(void)
{
return xt_register_target(&ebt_mpls_tg_reg);
}
static void __exit ebt_mpls_fini(void)
{
xt_unregister_target(&ebt_mpls_tg_reg);
}
module_init(ebt_mpls_init);
module_exit(ebt_mpls_fini);
MODULE_DESCRIPTION("Ebtables: MPLS forwarding");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,28 @@
/*
* ebt_mpls
*
* Authors:
* Markus Gothe <markus.gothe@genexis.eu>
*
* January, 2025
* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
*/
#ifndef __LINUX_BRIDGE_EBT_MPLS_H
#define __LINUX_BRIDGE_EBT_MPLS_H
#include <linux/types.h>
#include <linux/if_ether.h>
struct ebt_mpls_info
{
__be16 protocol;
__be32 label;
int target;
bool decap;
bool multicast;
uint8_t bitmask;
uint8_t invflags;
};
#endif