|
@@ -285,6 +285,45 @@ static struct Qdisc_ops *qdisc_lookup_ops(struct nlattr *kind)
|
|
|
return q;
|
|
|
}
|
|
|
|
|
|
+/* The linklayer setting were not transferred from iproute2, in older
|
|
|
+ * versions, and the rate tables lookup systems have been dropped in
|
|
|
+ * the kernel. To keep backward compatible with older iproute2 tc
|
|
|
+ * utils, we detect the linklayer setting by detecting if the rate
|
|
|
+ * table were modified.
|
|
|
+ *
|
|
|
+ * For linklayer ATM table entries, the rate table will be aligned to
|
|
|
+ * 48 bytes, thus some table entries will contain the same value. The
|
|
|
+ * mpu (min packet unit) is also encoded into the old rate table, thus
|
|
|
+ * starting from the mpu, we find low and high table entries for
|
|
|
+ * mapping this cell. If these entries contain the same value, when
|
|
|
+ * the rate tables have been modified for linklayer ATM.
|
|
|
+ *
|
|
|
+ * This is done by rounding mpu to the nearest 48 bytes cell/entry,
|
|
|
+ * and then roundup to the next cell, calc the table entry one below,
|
|
|
+ * and compare.
|
|
|
+ */
|
|
|
+static __u8 __detect_linklayer(struct tc_ratespec *r, __u32 *rtab)
|
|
|
+{
|
|
|
+ int low = roundup(r->mpu, 48);
|
|
|
+ int high = roundup(low+1, 48);
|
|
|
+ int cell_low = low >> r->cell_log;
|
|
|
+ int cell_high = (high >> r->cell_log) - 1;
|
|
|
+
|
|
|
+ /* rtab is too inaccurate at rates > 100Mbit/s */
|
|
|
+ if ((r->rate > (100000000/8)) || (rtab[0] == 0)) {
|
|
|
+ pr_debug("TC linklayer: Giving up ATM detection\n");
|
|
|
+ return TC_LINKLAYER_ETHERNET;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((cell_high > cell_low) && (cell_high < 256)
|
|
|
+ && (rtab[cell_low] == rtab[cell_high])) {
|
|
|
+ pr_debug("TC linklayer: Detected ATM, low(%d)=high(%d)=%u\n",
|
|
|
+ cell_low, cell_high, rtab[cell_high]);
|
|
|
+ return TC_LINKLAYER_ATM;
|
|
|
+ }
|
|
|
+ return TC_LINKLAYER_ETHERNET;
|
|
|
+}
|
|
|
+
|
|
|
static struct qdisc_rate_table *qdisc_rtab_list;
|
|
|
|
|
|
struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *tab)
|
|
@@ -308,6 +347,8 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *ta
|
|
|
rtab->rate = *r;
|
|
|
rtab->refcnt = 1;
|
|
|
memcpy(rtab->data, nla_data(tab), 1024);
|
|
|
+ if (r->linklayer == TC_LINKLAYER_UNAWARE)
|
|
|
+ r->linklayer = __detect_linklayer(r, rtab->data);
|
|
|
rtab->next = qdisc_rtab_list;
|
|
|
qdisc_rtab_list = rtab;
|
|
|
}
|