@@ -76,6 +76,14 @@ Description:
is used to classify clients as "isolated" by the
Extended Isolation feature.
+What: /sys/class/net/<mesh_iface>/mesh/noflood_mark
+Date: Mar 2018
+Contact: Linus Lüssing <linus.luessing@c0d3.blue>
+Description:
+ Defines the noflood mark (and its bitmask) which
+ will drop frames with a matching mark if they were
+ to be flooded.
+
What: /sys/class/net/<mesh_iface>/mesh/multicast_mode
Date: Feb 2014
Contact: Linus Lüssing <linus.luessing@web.de>
@@ -188,6 +188,23 @@ static void batadv_interface_set_rx_mode(struct net_device *dev)
{
}
+/**
+ * batadv_send_skb_has_noflood_mark() - check if packet has a noflood mark
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the packet to check
+ *
+ * Return: True if the skb's mark matches a configured noflood mark and
+ * noflood mark mask. False otherwise.
+ */
+static bool
+batadv_skb_has_noflood_mark(struct batadv_priv *bat_priv, struct sk_buff *skb)
+{
+ u32 match_mark = skb->mark & bat_priv->noflood_mark_mask;
+
+ return bat_priv->noflood_mark_mask &&
+ match_mark == bat_priv->noflood_mark;
+}
+
static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
struct net_device *soft_iface)
{
@@ -333,6 +350,9 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
brd_delay = msecs_to_jiffies(ARP_REQ_DELAY);
+ if (batadv_skb_has_noflood_mark(bat_priv, skb))
+ goto dropped;
+
if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0)
goto dropped;
@@ -618,28 +618,24 @@ static ssize_t batadv_show_isolation_mark(struct kobject *kobj,
}
/**
- * batadv_store_isolation_mark() - parse and store the isolation mark/mask
- * entered by the user
- * @kobj: kobject representing the private mesh sysfs directory
- * @attr: the batman-adv attribute the user is interacting with
+ * batadv_store_parse_mark() - parse a mark and mask
* @buff: the buffer containing the user data
- * @count: number of bytes in the buffer
+ * @mark: the variable to store the mark in
+ * @mask: the variable to store the mask in
*
- * Return: 'count' on success or a negative error code in case of failure
+ * Parses a string for a mark and mask. The format is expected to consist of
+ * two 32 bit hexadecimal numbers delimited by a '/'.
+ *
+ * Return: 0 on success, -EINVAL on error.
*/
-static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
- struct attribute *attr, char *buff,
- size_t count)
+static int batadv_store_parse_mark(char *buff, u32 *mark, u32 *mask)
{
- struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
- struct batadv_priv *bat_priv = netdev_priv(net_dev);
- u32 mark, mask;
char *mask_ptr;
/* parse the mask if it has been specified, otherwise assume the mask is
* the biggest possible
*/
- mask = 0xFFFFFFFF;
+ *mask = 0xFFFFFFFF;
mask_ptr = strchr(buff, '/');
if (mask_ptr) {
*mask_ptr = '\0';
@@ -648,12 +644,36 @@ static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
/* the mask must be entered in hex base as it is going to be a
* bitmask and not a prefix length
*/
- if (kstrtou32(mask_ptr, 16, &mask) < 0)
+ if (kstrtou32(mask_ptr, 16, mask) < 0)
return -EINVAL;
}
/* the mark can be entered in any base */
- if (kstrtou32(buff, 0, &mark) < 0)
+ if (kstrtou32(buff, 0, mark) < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * batadv_store_isolation_mark() - parse and store the isolation mark/mask
+ * entered by the user
+ * @kobj: kobject representing the private mesh sysfs directory
+ * @attr: the batman-adv attribute the user is interacting with
+ * @buff: the buffer containing the user data
+ * @count: number of bytes in the buffer
+ *
+ * Return: 'count' on success or a negative error code in case of failure
+ */
+static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
+ struct attribute *attr, char *buff,
+ size_t count)
+{
+ struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
+ struct batadv_priv *bat_priv = netdev_priv(net_dev);
+ u32 mark, mask;
+
+ if (batadv_store_parse_mark(buff, &mark, &mask) < 0)
return -EINVAL;
bat_priv->isolation_mark_mask = mask;
@@ -667,6 +687,56 @@ static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
return count;
}
+/**
+ * batadv_show_noflood_mark() - print the current noflood mark/mask
+ * @kobj: kobject representing the private mesh sysfs directory
+ * @attr: the batman-adv attribute the user is interacting with
+ * @buff: the buffer that will contain the data to send back to the user
+ *
+ * Return: the number of bytes written into 'buff' on success or a negative
+ * error code in case of failure
+ */
+static ssize_t batadv_show_noflood_mark(struct kobject *kobj,
+ struct attribute *attr, char *buff)
+{
+ struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
+
+ return sprintf(buff, "%#.8x/%#.8x\n", bat_priv->noflood_mark,
+ bat_priv->noflood_mark_mask);
+}
+
+/**
+ * batadv_store_noflood_mark() - parse and store the noflood mark/mask
+ * entered by the user
+ * @kobj: kobject representing the private mesh sysfs directory
+ * @attr: the batman-adv attribute the user is interacting with
+ * @buff: the buffer containing the user data
+ * @count: number of bytes in the buffer
+ *
+ * Return: 'count' on success or a negative error code in case of failure
+ */
+static ssize_t batadv_store_noflood_mark(struct kobject *kobj,
+ struct attribute *attr, char *buff,
+ size_t count)
+{
+ struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
+ struct batadv_priv *bat_priv = netdev_priv(net_dev);
+ u32 mark, mask;
+
+ if (batadv_store_parse_mark(buff, &mark, &mask) < 0)
+ return -EINVAL;
+
+ bat_priv->noflood_mark_mask = mask;
+ /* erase bits not covered by the mask */
+ bat_priv->noflood_mark = mark & bat_priv->noflood_mark_mask;
+
+ batadv_info(net_dev,
+ "New skb noflood mark: %#.8x/%#.8x\n",
+ bat_priv->noflood_mark, bat_priv->noflood_mark_mask);
+
+ return count;
+}
+
BATADV_ATTR_SIF_BOOL(aggregated_ogms, 0644, NULL);
BATADV_ATTR_SIF_BOOL(bonding, 0644, NULL);
#ifdef CONFIG_BATMAN_ADV_BLA
@@ -697,6 +767,8 @@ BATADV_ATTR_SIF_BOOL(network_coding, 0644, batadv_nc_status_update);
#endif
static BATADV_ATTR(isolation_mark, 0644, batadv_show_isolation_mark,
batadv_store_isolation_mark);
+static BATADV_ATTR(noflood_mark, 0644, batadv_show_noflood_mark,
+ batadv_store_noflood_mark);
static struct batadv_attribute *batadv_mesh_attrs[] = {
&batadv_attr_aggregated_ogms,
@@ -724,6 +796,7 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
&batadv_attr_network_coding,
#endif
&batadv_attr_isolation_mark,
+ &batadv_attr_noflood_mark,
NULL,
};
@@ -1584,6 +1584,18 @@ struct batadv_priv {
*/
u32 isolation_mark_mask;
+ /**
+ * @noflood_mark: the skb->mark value used to allow directed targeting
+ * only
+ */
+ u32 noflood_mark;
+
+ /**
+ * @noflood_mark_mask: bitmask identifying the bits in skb->mark to be
+ * used for the noflood mark
+ */
+ u32 noflood_mark_mask;
+
/** @bcast_seqno: last sent broadcast packet sequence number */
atomic_t bcast_seqno;